replicant-packages_apps_Email/tests/src/com/android/emailcommon/utility/UtilityUnitTests.java

559 lines
21 KiB
Java

/*
* Copyright (C) 2008 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.emailcommon.utility;
import com.android.email.DBTestHelper;
import com.android.email.FolderProperties;
import com.android.email.R;
import com.android.email.TestUtils;
import com.android.email.UiUtilities;
import com.android.email.provider.ProviderTestUtils;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Attachment;
import com.android.emailcommon.provider.EmailContent.Mailbox;
import com.android.emailcommon.utility.Utility.NewFileCreator;
import android.content.Context;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.database.MatrixCursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
import android.test.AndroidTestCase;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.widget.ListView;
import android.widget.TextView;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
/**
* This is a series of unit tests for the Utility class. These tests must be locally
* complete - no server(s) required.
*
* You can run this entire test case with:
* runtest -c com.android.email.UtilityUnitTests email
*/
@SmallTest
public class UtilityUnitTests extends AndroidTestCase {
/**
* Tests of the IMAP quoting rules function.
*/
public void testImapQuote() {
// Simple strings should come through with simple quotes
assertEquals("\"abcd\"", Utility.imapQuoted("abcd"));
// Quoting internal double quotes with \
assertEquals("\"ab\\\"cd\"", Utility.imapQuoted("ab\"cd"));
// Quoting internal \ with \\
assertEquals("\"ab\\\\cd\"", Utility.imapQuoted("ab\\cd"));
}
/**
* Tests of the syncronization of array and types of the display folder names
*/
public void testGetDisplayName() {
Context context = getContext();
String expect, name;
expect = context.getString(R.string.mailbox_name_display_inbox);
name = FolderProperties.getInstance(context).getDisplayName(Mailbox.TYPE_INBOX);
assertEquals(expect, name);
expect = null;
name = FolderProperties.getInstance(context).getDisplayName(Mailbox.TYPE_MAIL);
assertEquals(expect, name);
expect = null;
name = FolderProperties.getInstance(context).getDisplayName(Mailbox.TYPE_PARENT);
assertEquals(expect, name);
expect = context.getString(R.string.mailbox_name_display_drafts);
name = FolderProperties.getInstance(context).getDisplayName(Mailbox.TYPE_DRAFTS);
assertEquals(expect, name);
expect = context.getString(R.string.mailbox_name_display_outbox);
name = FolderProperties.getInstance(context).getDisplayName(Mailbox.TYPE_OUTBOX);
assertEquals(expect, name);
expect = context.getString(R.string.mailbox_name_display_sent);
name = FolderProperties.getInstance(context).getDisplayName(Mailbox.TYPE_SENT);
assertEquals(expect, name);
expect = context.getString(R.string.mailbox_name_display_trash);
name = FolderProperties.getInstance(context).getDisplayName(Mailbox.TYPE_TRASH);
assertEquals(expect, name);
expect = context.getString(R.string.mailbox_name_display_junk);
name = FolderProperties.getInstance(context).getDisplayName(Mailbox.TYPE_JUNK);
assertEquals(expect, name);
// Testing illegal index
expect = null;
name = FolderProperties.getInstance(context).getDisplayName(8);
assertEquals(expect, name);
}
/**
* Confirm that all of the special icons are available and unique
*/
public void testSpecialIcons() {
FolderProperties fp = FolderProperties.getInstance(mContext);
// Make sure they're available
Drawable inbox = fp.getIcon(Mailbox.TYPE_INBOX, -1);
Drawable mail = fp.getIcon(Mailbox.TYPE_MAIL, -1);
Drawable parent = fp.getIcon(Mailbox.TYPE_PARENT, -1);
Drawable drafts = fp.getIcon(Mailbox.TYPE_DRAFTS, -1);
Drawable outbox = fp.getIcon(Mailbox.TYPE_OUTBOX, -1);
Drawable sent = fp.getIcon(Mailbox.TYPE_SENT, -1);
Drawable trash = fp.getIcon(Mailbox.TYPE_TRASH, -1);
Drawable junk = fp.getIcon(Mailbox.TYPE_JUNK, -1);
// Make sure they're unique
Set<Drawable> set = new HashSet<Drawable>();
set.add(inbox);
set.add(parent);
set.add(drafts);
set.add(outbox);
set.add(sent);
set.add(trash);
set.add(junk);
assertEquals(7, set.size());
assertNull(mail);
}
private static byte[] b(int... array) {
return TestUtils.b(array);
}
public void testToUtf8() {
assertNull(Utility.toUtf8(null));
MoreAsserts.assertEquals(new byte[] {}, Utility.toUtf8(""));
MoreAsserts.assertEquals(b('a'), Utility.toUtf8("a"));
MoreAsserts.assertEquals(b('A', 'B', 'C'), Utility.toUtf8("ABC"));
MoreAsserts.assertEquals(b(0xE6, 0x97, 0xA5, 0xE6, 0x9C, 0xAC, 0xE8, 0xAA, 0x9E),
Utility.toUtf8("\u65E5\u672C\u8A9E"));
}
public void testFromUtf8() {
assertNull(Utility.fromUtf8(null));
assertEquals("", Utility.fromUtf8(new byte[] {}));
assertEquals("a", Utility.fromUtf8(b('a')));
assertEquals("ABC", Utility.fromUtf8(b('A', 'B', 'C')));
assertEquals("\u65E5\u672C\u8A9E",
Utility.fromUtf8(b(0xE6, 0x97, 0xA5, 0xE6, 0x9C, 0xAC, 0xE8, 0xAA, 0x9E)));
}
public void testIsFirstUtf8Byte() {
// 1 byte in UTF-8.
checkIsFirstUtf8Byte("0"); // First 2 bits: 00
checkIsFirstUtf8Byte("A"); // First 2 bits: 01
checkIsFirstUtf8Byte("\u00A2"); // 2 bytes in UTF-8.
checkIsFirstUtf8Byte("\u20AC"); // 3 bytes in UTF-8.
checkIsFirstUtf8Byte("\uD852\uDF62"); // 4 bytes in UTF-8. (surrogate pair)
}
private void checkIsFirstUtf8Byte(String aChar) {
byte[] bytes = Utility.toUtf8(aChar);
assertTrue("0", Utility.isFirstUtf8Byte(bytes[0]));
for (int i = 1; i < bytes.length; i++) {
assertFalse(Integer.toString(i), Utility.isFirstUtf8Byte(bytes[i]));
}
}
public void testByteToHex() {
for (int i = 0; i <= 0xFF; i++) {
String hex = Utility.byteToHex((byte) i);
assertEquals("val=" + i, 2, hex.length());
assertEquals("val=" + i, i, Integer.parseInt(hex, 16));
}
}
public void testReplaceBareLfWithCrlf() {
assertEquals("", Utility.replaceBareLfWithCrlf(""));
assertEquals("", Utility.replaceBareLfWithCrlf("\r"));
assertEquals("\r\n", Utility.replaceBareLfWithCrlf("\r\n"));
assertEquals("\r\n", Utility.replaceBareLfWithCrlf("\n"));
assertEquals("\r\n\r\n\r\n", Utility.replaceBareLfWithCrlf("\n\n\n"));
assertEquals("A\r\nB\r\nC\r\nD", Utility.replaceBareLfWithCrlf("A\nB\r\nC\nD"));
}
public void testGetSmallHash() {
assertEquals("1438642069", Utility.getSmallHash(""));
assertEquals("1354919068", Utility.getSmallHash("abc"));
}
public void testGetSmallSha1() {
byte[] sha1 = new byte[20];
// White box test. Not so great, but to make sure it may detect careless mistakes...
assertEquals(0, Utility.getSmallHashFromSha1(sha1));
for (int i = 0; i < sha1.length; i++) {
sha1[i] = (byte) 0xFF;
}
assertEquals(Integer.MAX_VALUE, Utility.getSmallHashFromSha1(sha1));
// Boundary check
for (int i = 0; i < 16; i++) {
sha1[19] = (byte) i;
Utility.getSmallHashFromSha1(sha1);
}
}
public void testCleanUpMimeDate() {
assertNull(Utility.cleanUpMimeDate(null));
assertEquals("", Utility.cleanUpMimeDate(""));
assertEquals("abc", Utility.cleanUpMimeDate("abc"));
assertEquals("GMT", Utility.cleanUpMimeDate("GMT"));
assertEquals("0000", Utility.cleanUpMimeDate("0000"));
assertEquals("-0000", Utility.cleanUpMimeDate("-0000"));
assertEquals("+1234", Utility.cleanUpMimeDate("GMT+1234"));
assertEquals("-1234", Utility.cleanUpMimeDate("GMT-1234"));
assertEquals("gmt-1234", Utility.cleanUpMimeDate("gmt-1234"));
assertEquals("GMT-123", Utility.cleanUpMimeDate("GMT-123"));
assertEquals("Thu, 10 Dec 09 15:08:08 -0700",
Utility.cleanUpMimeDate("Thu, 10 Dec 09 15:08:08 GMT-0700"));
assertEquals("Thu, 10 Dec 09 15:08:08 -0700",
Utility.cleanUpMimeDate("Thu, 10 Dec 09 15:08:08 -0700"));
}
public void testFormatSize() {
if (!"en".equalsIgnoreCase(Locale.getDefault().getLanguage())) {
return; // Only works on the EN locale.
}
assertEquals("0B", UiUtilities.formatSize(getContext(), 0));
assertEquals("1B", UiUtilities.formatSize(getContext(), 1));
assertEquals("1023B", UiUtilities.formatSize(getContext(), 1023));
assertEquals("1KB", UiUtilities.formatSize(getContext(), 1024));
assertEquals("1023KB", UiUtilities.formatSize(getContext(), 1024 * 1024 - 1));
assertEquals("1MB", UiUtilities.formatSize(getContext(), 1024 * 1024));
assertEquals("1023MB", UiUtilities.formatSize(getContext(), 1024 * 1024 * 1024 - 1));
assertEquals("1GB", UiUtilities.formatSize(getContext(), 1024 * 1024 * 1024));
assertEquals("5GB", UiUtilities.formatSize(getContext(), 5L * 1024 * 1024 * 1024));
}
private static class MyNewFileCreator implements NewFileCreator {
private final HashSet<String> mExistingFileNames;
public MyNewFileCreator(String... fileNames) {
mExistingFileNames = new HashSet<String>();
for (String f : fileNames) {
mExistingFileNames.add(f);
}
}
@Override public boolean createNewFile(File f) {
return !mExistingFileNames.contains(f.getAbsolutePath());
}
}
public void testCreateUniqueFile() throws Exception {
final MyNewFileCreator noFiles = new MyNewFileCreator();
// Case 1: Files don't exist.
checkCreateUniqueFile("/a", noFiles, "/", "a");
checkCreateUniqueFile("/a.txt", noFiles, "/", "a.txt");
checkCreateUniqueFile("/a/b/a", noFiles, "/a/b", "a");
checkCreateUniqueFile("/a/b/a.txt", noFiles, "/a/b", "a.txt");
// Case 2: Files exist already.
final MyNewFileCreator files = new MyNewFileCreator(
"/a", "/a.txt", "/a/b/a", "/a/b/a.txt",
"/a-2.txt",
"/a/b/a-2", "/a/b/a-3",
"/a/b/a-2.txt", "/a/b/a-3.txt", "/a/b/a-4.txt"
);
checkCreateUniqueFile("/a-2", files, "/", "a");
checkCreateUniqueFile("/a-3.txt", files, "/", "a.txt");
checkCreateUniqueFile("/a/b/a-4", files, "/a/b", "a");
checkCreateUniqueFile("/a/b/a-5.txt", files, "/a/b", "a.txt");
}
private void checkCreateUniqueFile(String expectedFileName, NewFileCreator nfc,
String dir, String fileName) throws Exception {
assertEquals(expectedFileName,
Utility.createUniqueFileInternal(nfc, new File(dir), fileName).toString());
}
/**
* Test that we have the necessary permissions to write to external storage.
*/
public void testExternalStoragePermissions() throws FileNotFoundException, IOException {
File file = null;
try {
// If there's no storage available, this test is moot
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return;
}
file = Utility.createUniqueFile(Environment.getExternalStorageDirectory(),
"write-test");
OutputStream out = new FileOutputStream(file);
out.write(1);
out.close();
} finally {
try {
if (file != null) {
if (file.exists()) {
file.delete();
}
}
} catch (Exception e) {
// ignore cleanup error - it still throws the original
}
}
}
public void testIsPortFieldValid() {
TextView view = new TextView(getContext());
// null, empty, negative, and non integer strings aren't valid
view.setText(null);
assertFalse(Utility.isPortFieldValid(view));
view.setText("");
assertFalse(Utility.isPortFieldValid(view));
view.setText("-1");
assertFalse(Utility.isPortFieldValid(view));
view.setText("1403.75");
assertFalse(Utility.isPortFieldValid(view));
view.setText("0");
assertFalse(Utility.isPortFieldValid(view));
view.setText("65536");
assertFalse(Utility.isPortFieldValid(view));
view.setText("i'm not valid");
assertFalse(Utility.isPortFieldValid(view));
// These next values are valid
view.setText("1");
assertTrue(Utility.isPortFieldValid(view));
view.setText("65535");
assertTrue(Utility.isPortFieldValid(view));
}
public void testListStateSaver() {
final String BUNDLE_KEY = "a";
Bundle b = new Bundle();
// Create a list view, save the state.
// (Use blocks to make sure we won't use the same instance later.)
{
final MockListView lv1 = new MockListView(getContext());
lv1.mCustomData = 1;
final Utility.ListStateSaver lss1 = new Utility.ListStateSaver(lv1);
b.putParcelable(BUNDLE_KEY, lss1);
}
// Restore the state into a new list view.
{
final Utility.ListStateSaver lss2 = b.getParcelable(BUNDLE_KEY);
final MockListView lv2 = new MockListView(getContext());
lss2.restore(lv2);
assertEquals(1, lv2.mCustomData);
}
}
public void testToPrimitiveLongArray() {
assertEquals(0, Utility.toPrimitiveLongArray(createLongCollection()).length);
final long[] one = Utility.toPrimitiveLongArray(createLongCollection(1));
assertEquals(1, one.length);
assertEquals(1, one[0]);
final long[] two = Utility.toPrimitiveLongArray(createLongCollection(3, 4));
assertEquals(2, two.length);
assertEquals(3, two[0]);
assertEquals(4, two[1]);
}
public void testGetContentFileName() throws Exception {
Context providerContext = DBTestHelper.ProviderContextSetupHelper.getProviderContext(
mContext);
final long ACCOUNT_ID = 1;
final long MESSAGE_ID = 10;
Account account = ProviderTestUtils.setupAccount("account", true, providerContext);
Mailbox mailbox = ProviderTestUtils.setupMailbox("box", account.mId, true, providerContext);
// Set up an attachment.
Attachment att = ProviderTestUtils.setupAttachment(mailbox.mId, "name", 123, true,
providerContext);
long attachmentId = att.mId;
Uri uri = AttachmentUtilities.getAttachmentUri(account.mId, attachmentId);
// Case 1: exists in the provider.
assertEquals("name", Utility.getContentFileName(providerContext, uri));
// Case 2: doesn't exist in the provider
Uri notExistUri = AttachmentUtilities.getAttachmentUri(account.mId, 123456789);
String lastPathSegment = notExistUri.getLastPathSegment();
assertEquals(lastPathSegment, Utility.getContentFileName(providerContext, notExistUri));
}
private static Collection<Long> createLongCollection(long... values) {
ArrayList<Long> ret = new ArrayList<Long>();
for (long value : values) {
ret.add(value);
}
return ret;
}
public void testDumpCursor() {
// Just make sure the method won't crash and returns non-empty string.
final Cursor c1 = new MatrixCursor(new String[] {"col"});
final Cursor c2 = new CursorWrapper(c1);
// Note it's a subclass of CursorWrapper.
final Cursor c3 = new CursorWrapper(c2) {
};
assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c1)));
assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c2)));
assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c3)));
assertFalse(TextUtils.isEmpty(Utility.dumpCursor(null)));
// Test again with closed cursor.
c1.close();
assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c1)));
assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c2)));
assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c3)));
assertFalse(TextUtils.isEmpty(Utility.dumpCursor(null)));
}
public void testCloseTraceCursorWrapper() {
final Cursor org = new MatrixCursor(new String[] {"col"});
final Utility.CloseTraceCursorWrapper c =
Utility.CloseTraceCursorWrapper.alwaysCreateForTest(org);
// Not closed -- no stack trace
assertNull(Utility.CloseTraceCursorWrapper.getTraceIfAvailable(c));
Utility.CloseTraceCursorWrapper.log(c); // shouldn't crash
// Close, now stack trace should be available
c.close();
assertNotNull(Utility.CloseTraceCursorWrapper.getTraceIfAvailable(c));
Utility.CloseTraceCursorWrapper.log(c);
// shouldn't crash
Utility.CloseTraceCursorWrapper.log(null);
}
public void testAppendBold() {
SpannableStringBuilder ssb = new SpannableStringBuilder();
ssb.append("no");
assertEquals(ssb, Utility.appendBold(ssb, "BO"));
assertEquals("noBO", ssb.toString());
// TODO check style -- but how?
}
public void testGetMessageCountForUi() {
final Context c = getContext();
// Negavive valeus not really expected, but at least shouldn't crash.
assertEquals("-1", UiUtilities.getMessageCountForUi(c, -1, true));
assertEquals("-1", UiUtilities.getMessageCountForUi(c, -1, false));
assertEquals("", UiUtilities.getMessageCountForUi(c, 0, true));
assertEquals("0", UiUtilities.getMessageCountForUi(c, 0, false));
assertEquals("1", UiUtilities.getMessageCountForUi(c, 1, true));
assertEquals("1", UiUtilities.getMessageCountForUi(c, 1, false));
assertEquals("999", UiUtilities.getMessageCountForUi(c, 999, true));
assertEquals("999", UiUtilities.getMessageCountForUi(c, 999, false));
final String moreThan999 = c.getString(R.string.more_than_999);
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1000, true));
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1000, false));
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1001, true));
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1001, false));
}
/**
* A {@link ListView} used by {@link #testListStateSaver}.
*/
private static class MockListView extends ListView {
public int mCustomData;
public MockListView(Context context) {
super(context);
}
@Override
public Parcelable onSaveInstanceState() {
SavedState ss = new SavedState(super.onSaveInstanceState());
ss.mCustomData = mCustomData;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
mCustomData = ss.mCustomData;
}
static class SavedState extends BaseSavedState {
public int mCustomData;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
in.writeInt(mCustomData);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
mCustomData = out.readInt();
}
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
}