package it.geosolutions.android.mapstoremobiletestframe.test; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mapsforge.android.maps.mapgenerator.MapGeneratorJob; import org.mapsforge.android.maps.mapgenerator.mbtiles.MbTilesDatabaseRenderer; import org.mapsforge.core.model.BoundingBox; import org.mapsforge.core.model.GeoPoint; import org.mapsforge.core.model.Tile; import android.content.Context; import android.graphics.Bitmap; import android.test.InstrumentationTestCase; import android.util.Log; /** * class to test the functionalities of the MBTiles renderer integrated into Mapsforge * * @author Robert Oehler * */ public class MBTilesBackgroundRendererTest extends InstrumentationTestCase { private Context mContext; private final static String TAG = MBTilesBackgroundRendererTest.class.getSimpleName(); private MbTilesDatabaseRenderer mbTilesDatabaseRenderer; @Override public void setUp() throws Exception { super.setUp(); mContext = getInstrumentation().getTargetContext(); assertNotNull(mContext); //it is necessary to copy the test mbtiles file from assets to the internal memory as otherwise it cannot be read final String targetPath = getInstrumentation().getTargetContext().getApplicationInfo().dataDir+ "/test.mbtiles"; File file = new File(targetPath); //check if already done on earlier launch, when not -> copy if(!file.exists()){ try { InputStream is = getInstrumentation().getContext().getAssets().open("premium-snowdepth.mbtiles"); copyFile(is, targetPath); file = new File(targetPath); } catch (IOException e) { Log.e(TAG, "error testMapView",e); } } //now the file should be available always assertTrue(file.exists()); mbTilesDatabaseRenderer = new MbTilesDatabaseRenderer(mContext, targetPath); } public void tearDown() throws Exception { mbTilesDatabaseRenderer.destroy(); super.tearDown(); } /** * tests the extraction of tiles from the database */ public void testExecuteJob(){ //open its database mbTilesDatabaseRenderer.start(); //it should be working boolean isWorking = mbTilesDatabaseRenderer.isWorking(); assertTrue(isWorking); //now test the database, these are valid coordinates for the file premium-snowdepth.mbtiles provided in assets final int[] validDBCoords = {540,658,10}; //these instead should always be invalid final int[] invalidDBCoords = {5400,363,10}; //as the renderer converts from Google coords to TMS coords, convert here the tms coords to google coords final int[] validGoogleCoords = tmsTile2GoogleTile(validDBCoords[0], validDBCoords[1], validDBCoords[2]); final int[] invalidGoogleCoords = tmsTile2GoogleTile(invalidDBCoords[0], invalidDBCoords[1], invalidDBCoords[2]); //create tiles final Tile validTile = new Tile(validGoogleCoords[0], validGoogleCoords[1],(byte) validDBCoords[2]); final Tile invalidTile = new Tile(invalidGoogleCoords[0], invalidGoogleCoords[1],(byte) invalidDBCoords[2]); //jobs final MapGeneratorJob validJob = new MapGeneratorJob(validTile, null, null, null); final MapGeneratorJob invalidJob = new MapGeneratorJob(invalidTile, null, null, null); //empty bitmaps Bitmap validBitmap = Bitmap.createBitmap(Tile.TILE_SIZE, Tile.TILE_SIZE, Bitmap.Config.RGB_565); Bitmap invalidBitmap = Bitmap.createBitmap(Tile.TILE_SIZE, Tile.TILE_SIZE, Bitmap.Config.RGB_565); //start a valid query, only in severe error scenarios this will fail e.g. for invalid tiles with zoom > 11 assertTrue(mbTilesDatabaseRenderer.executeJob(validJob, validBitmap)); //invalid query assertTrue(mbTilesDatabaseRenderer.executeJob(invalidJob,invalidBitmap)); //prepare pixel arrays for evaluation int[] validPixels = new int[Tile.TILE_SIZE * Tile.TILE_SIZE]; int[] invalidPixels = new int[Tile.TILE_SIZE * Tile.TILE_SIZE]; //fill them with the bitmap pixels validBitmap.getPixels(validPixels, 0, Tile.TILE_SIZE, 0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE); invalidBitmap.getPixels(invalidPixels, 0, Tile.TILE_SIZE, 0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE); //check the valid pixels, they should not all be white for a non white tile boolean allValidPixelsAreWhite = true; for(int i = 0; i < validPixels.length; i++){ //get value int validPixel = validPixels[i]; //extract r,g and b int valid_r = (validPixel >> 16) & 0xff; int valid_g = (validPixel >> 8) & 0xff; int valid_b = (validPixel) & 0xff; //if one component is not white, this will turn to false allValidPixelsAreWhite = valid_r == 255 && valid_g == 255 && valid_b == 255; if(!allValidPixelsAreWhite){ //not white, no need to go on break; } } //check at least on component of one pixel was not white assertFalse(allValidPixelsAreWhite); //instead for invalid tiles, all pixels should be white boolean allInvalidPixelsAreWhite = false; for(int j = 0; j < invalidPixels.length; j++){ int invalidPixel = invalidPixels[j]; int invalid_r = (invalidPixel >> 16) & 0xff; int invalid_g = (invalidPixel >> 8) & 0xff; int invalid_b = (invalidPixel) & 0xff; //this will turn to false if one component is not white allInvalidPixelsAreWhite = (invalid_r == 255 && invalid_g == 255 && invalid_b == 255); if(!allInvalidPixelsAreWhite){ //failure, something was not white break; } } //all should have been white assertTrue(allInvalidPixelsAreWhite); //clean up validBitmap.recycle(); invalidBitmap.recycle(); mbTilesDatabaseRenderer.stop(); } public void testMbTilesBoundingBox(){ mbTilesDatabaseRenderer.start(); final BoundingBox bb = mbTilesDatabaseRenderer.getBoundingBox(); assertNotNull(bb); //premium-snowdepth.mbtiles dependent values final BoundingBox pSDBB = new BoundingBox(45.3308271267531,8.55646534342289,47.34943607332579,13.787875316072201); assertEquals(bb.maxLatitude, pSDBB.maxLatitude, 0.000001); assertEquals(bb.minLatitude, pSDBB.minLatitude, 0.000001); assertEquals(bb.maxLongitude, pSDBB.maxLongitude, 0.000001); assertEquals(bb.minLongitude, pSDBB.minLongitude, 0.000001); mbTilesDatabaseRenderer.stop(); } /** * tests the database metadata boundingbox and its resulting start (center) point */ public void testStartPoint(){ mbTilesDatabaseRenderer.start(); final GeoPoint center = mbTilesDatabaseRenderer.getStartPoint(); assertNotNull(center); //this returns in case of error a default center, check that this did not happen assertNotSame(center, new GeoPoint(43.7242359188, 10.9463005959)); //premium-snowdepth.mbtiles dependent values final BoundingBox pSDBB = new BoundingBox(45.3308271267531,8.55646534342289,47.34943607332579,13.787875316072201); final GeoPoint pSDCenter = pSDBB.getCenterPoint(); assertEquals(center, pSDCenter); mbTilesDatabaseRenderer.stop(); } public void copyFile(InputStream is, String target){ OutputStream outputStream = null; try { // write the inputStream to a FileOutputStream outputStream = new FileOutputStream(new File(target)); int read = 0; byte[] bytes = new byte[1024]; while ((read = is.read(bytes)) != -1) { outputStream.write(bytes, 0, read); } Log.d(TAG, "done copying"); } catch (IOException e) { Log.e(TAG, "error saveFile",e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { Log.e(TAG, "error saveFile",e); } } if (outputStream != null) { try { outputStream.flush(); outputStream.close(); } catch (IOException e) { Log.e(TAG, "error saveFile",e); } } } } public static int[] tmsTile2GoogleTile( int tx, int ty, int zoom ) { return new int[]{tx, (int) ((Math.pow(2, zoom) - 1) - ty)}; } }