/******************************************************************************* * Copyright 2012-present Pixate, Inc. * * 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.pixate.util; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import android.annotation.TargetApi; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.os.Build; import android.test.AndroidTestCase; import android.util.Base64; import android.util.Base64OutputStream; import com.pixate.PixateFreestyle; public class UrlStreamOpenerTests extends AndroidTestCase { private static final String RAW_TEST_FILE = "url_test_file"; private static final String IMAGE_RES = "ic_launcher.png"; private static final String IMAGE_ASSET = "urlOpener/asset_test.png"; private static final String DOCUMENT_FILE = "doc_test"; private static final String TMP_FILE = "tmp_test"; private String testFileContents; private String documentFileUri; private File tempFile; private Bitmap assetBitmap; private String assetBitmapBase64; public UrlStreamOpenerTests() { } @Override protected void setUp() throws Exception { super.setUp(); Context context = this.getContext(); PixateFreestyle.init(context.getApplicationContext()); // Grab the bitmap placed in the assets. We can use it to compare // results later. InputStream is = context.getAssets().open(IMAGE_ASSET); assetBitmap = BitmapFactory.decodeStream(is); is.close(); Resources resources = context.getResources(); int rawFileId = resources.getIdentifier(RAW_TEST_FILE, "raw", this.getContext().getPackageName()); testFileContents = readStream(resources.openRawResource(rawFileId)); // Create a document file. OutputStreamWriter writer = new OutputStreamWriter(getContext().openFileOutput(DOCUMENT_FILE, Context.MODE_PRIVATE)); try { writer.write(testFileContents); } finally { writer.close(); } // Learn the document file's file:// uri so we can test that scheme. documentFileUri = new File(context.getFilesDir(), DOCUMENT_FILE).toURI().toString(); // Clean it up to make it look like someone would type it in css // (file:// instead of just file:/) if (documentFileUri.startsWith("file:/") && !documentFileUri.startsWith("file://")) { documentFileUri = documentFileUri.replace("file:", "file://"); } // Create a temp file. tempFile = new File(context.getCacheDir(), TMP_FILE); writer = new OutputStreamWriter(new FileOutputStream(tempFile)); try { writer.write(testFileContents); } finally { writer.close(); } // Get a base64 of the test asset image bytes so we can do a data: call // and compare results. is = context.getAssets().open(IMAGE_ASSET); ByteArrayOutputStream output = new ByteArrayOutputStream(); Base64OutputStream bos = new Base64OutputStream(output, Base64.DEFAULT); try { byte[] buffer = new byte[2048]; int count = is.read(buffer); while (count > 0) { bos.write(buffer, 0, count); count = is.read(buffer); } assetBitmapBase64 = output.toString(); } finally { is.close(); bos.close(); } } @Override protected void tearDown() throws Exception { super.tearDown(); // Remove files created for the tests. // The document file. try { getContext().deleteFile(DOCUMENT_FILE); } catch (Exception e) { // No-op } // The temp file. try { if (tempFile != null && tempFile.exists()) { tempFile.delete(); } } catch (Exception e) { // no-op } } public void testResourceBitmap() { Bitmap bitmap = new BitmapDrawable(getContext().getResources(), UrlStreamOpener.open("bundle://" + IMAGE_RES)).getBitmap(); assertNotNull("Bitmap not created", bitmap); assertTrue("Returned bitmap too small to be valid", bitmap.getHeight() > 10 && bitmap.getWidth() > 10); } public void testResourceText() throws Exception { assertEquals(testFileContents, readStream(UrlStreamOpener.open("bundle://" + RAW_TEST_FILE))); } public void testAssetBitmap() throws Exception { InputStream is = UrlStreamOpener.open("bundle://" + IMAGE_ASSET); try { Bitmap bitmap = BitmapFactory.decodeStream(is); boolean result; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { result = checkSameBitmapHC(assetBitmap, bitmap); } else { result = checkSameBitmapGB(assetBitmap, bitmap); } assertTrue("Returned bitmap different than canonical bitmap", result); } finally { is.close(); } } public void testDocument() throws Exception { assertEquals(testFileContents, readStream(UrlStreamOpener.open("documents://" + DOCUMENT_FILE))); } public void testFile() throws Exception { assertEquals(testFileContents, readStream(UrlStreamOpener.open(documentFileUri))); } public void testTmp() throws Exception { assertEquals(testFileContents, readStream(UrlStreamOpener.open("tmp://" + TMP_FILE))); } public void testData() throws Exception { InputStream is = UrlStreamOpener.open("data:image/png;base64," + assetBitmapBase64); try { Bitmap bitmap = BitmapFactory.decodeStream(is); boolean result; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { result = checkSameBitmapHC(assetBitmap, bitmap); } else { result = checkSameBitmapGB(assetBitmap, bitmap); } assertTrue("Returned bitmap different than canonical bitmap", result); } finally { is.close(); } } public void testImplicitDocument() throws Exception { // Document is checked first. This matches the test // document file name, so it should work. assertEquals(testFileContents, readStream(UrlStreamOpener.open(DOCUMENT_FILE))); } public void testImplicitBundleAsset() throws Exception { // Bundle is checked after documents. This is a valid // file name in assets (a bundle source), so it should be found. InputStream is = UrlStreamOpener.open(IMAGE_ASSET); assertNotNull(is); try { Bitmap bitmap = BitmapFactory.decodeStream(is); boolean result; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { result = checkSameBitmapHC(assetBitmap, bitmap); } else { result = checkSameBitmapGB(assetBitmap, bitmap); } assertTrue("Returned bitmap different than canonical bitmap", result); } finally { is.close(); } } // Private // Also closes the stream. private String readStream(InputStream is) throws Exception { if (is == null) { return null; } char[] buffer = new char[2048]; StringBuilder sb = new StringBuilder(); InputStreamReader reader = new InputStreamReader(is, "utf-8"); int count = reader.read(buffer); while (count > 0) { sb.append(buffer, 0, count); count = reader.read(buffer); } is.close(); return sb.toString(); } @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) private boolean checkSameBitmapHC(Bitmap b1, Bitmap b2) { if (b1 == null || b2 == null) { return false; } return b1.sameAs(b2); } private boolean checkSameBitmapGB(Bitmap b1, Bitmap b2) { if (b1 != null && b1 == b2) { return true; } if (b1 == null || b2 == null) { return false; } // Poor man's comparison for Gingerbread. return b1.getHeight() == b2.getHeight() && b1.getWidth() == b2.getWidth() && b1.getRowBytes() == b2.getRowBytes() && b1.getPixel(0, 0) == b2.getPixel(0, 0) && b1.getPixel(b1.getWidth() - 1, b1.getHeight() - 1) == b2.getPixel(b2.getWidth() - 1, b2.getHeight() - 1); } }