Home | History | Annotate | Download | only in utility
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.emailcommon.utility;
     18 
     19 import android.content.Context;
     20 import android.database.Cursor;
     21 import android.database.CursorWrapper;
     22 import android.net.Uri;
     23 import android.os.Environment;
     24 import android.test.AndroidTestCase;
     25 import android.test.MoreAsserts;
     26 import android.test.suitebuilder.annotation.SmallTest;
     27 import android.test.suitebuilder.annotation.Suppress;
     28 import android.text.SpannableStringBuilder;
     29 import android.text.TextUtils;
     30 import android.widget.TextView;
     31 
     32 import com.android.email.DBTestHelper;
     33 import com.android.email.TestUtils;
     34 import com.android.email.provider.ProviderTestUtils;
     35 import com.android.emailcommon.provider.Account;
     36 import com.android.emailcommon.provider.EmailContent.Attachment;
     37 import com.android.emailcommon.provider.Mailbox;
     38 import com.android.emailcommon.utility.Utility.NewFileCreator;
     39 import com.android.mail.utils.MatrixCursorWithCachedColumns;
     40 
     41 import java.io.File;
     42 import java.io.FileNotFoundException;
     43 import java.io.FileOutputStream;
     44 import java.io.IOException;
     45 import java.io.OutputStream;
     46 import java.util.ArrayList;
     47 import java.util.Collection;
     48 import java.util.HashSet;
     49 import java.util.Set;
     50 
     51 /**
     52  * This is a series of unit tests for the Utility class.  These tests must be locally
     53  * complete - no server(s) required.
     54  *
     55  * You can run this entire test case with:
     56  *   runtest -c com.android.email.UtilityUnitTests email
     57  */
     58 @Suppress
     59 @SmallTest
     60 public class UtilityUnitTests extends AndroidTestCase {
     61 
     62     private static byte[] b(int... array) {
     63         return TestUtils.b(array);
     64     }
     65 
     66     public void testToUtf8() {
     67         assertNull(Utility.toUtf8(null));
     68         MoreAsserts.assertEquals(new byte[] {}, Utility.toUtf8(""));
     69         MoreAsserts.assertEquals(b('a'), Utility.toUtf8("a"));
     70         MoreAsserts.assertEquals(b('A', 'B', 'C'), Utility.toUtf8("ABC"));
     71         MoreAsserts.assertEquals(b(0xE6, 0x97, 0xA5, 0xE6, 0x9C, 0xAC, 0xE8, 0xAA, 0x9E),
     72                 Utility.toUtf8("\u65E5\u672C\u8A9E"));
     73     }
     74 
     75     public void testFromUtf8() {
     76         assertNull(Utility.fromUtf8(null));
     77         assertEquals("", Utility.fromUtf8(new byte[] {}));
     78         assertEquals("a", Utility.fromUtf8(b('a')));
     79         assertEquals("ABC", Utility.fromUtf8(b('A', 'B', 'C')));
     80         assertEquals("\u65E5\u672C\u8A9E",
     81                 Utility.fromUtf8(b(0xE6, 0x97, 0xA5, 0xE6, 0x9C, 0xAC, 0xE8, 0xAA, 0x9E)));
     82     }
     83 
     84     public void testIsFirstUtf8Byte() {
     85         // 1 byte in UTF-8.
     86         checkIsFirstUtf8Byte("0"); // First 2 bits: 00
     87         checkIsFirstUtf8Byte("A"); // First 2 bits: 01
     88 
     89         checkIsFirstUtf8Byte("\u00A2"); // 2 bytes in UTF-8.
     90         checkIsFirstUtf8Byte("\u20AC"); // 3 bytes in UTF-8.
     91         checkIsFirstUtf8Byte("\uD852\uDF62"); // 4 bytes in UTF-8.  (surrogate pair)
     92     }
     93 
     94     private void checkIsFirstUtf8Byte(String aChar) {
     95         byte[] bytes = Utility.toUtf8(aChar);
     96         assertTrue("0", Utility.isFirstUtf8Byte(bytes[0]));
     97         for (int i = 1; i < bytes.length; i++) {
     98             assertFalse(Integer.toString(i), Utility.isFirstUtf8Byte(bytes[i]));
     99         }
    100     }
    101 
    102     public void testByteToHex() {
    103         for (int i = 0; i <= 0xFF; i++) {
    104             String hex = Utility.byteToHex((byte) i);
    105             assertEquals("val=" + i, 2, hex.length());
    106             assertEquals("val=" + i, i, Integer.parseInt(hex, 16));
    107         }
    108     }
    109 
    110     public void testReplaceBareLfWithCrlf() {
    111         assertEquals("", Utility.replaceBareLfWithCrlf(""));
    112         assertEquals("", Utility.replaceBareLfWithCrlf("\r"));
    113         assertEquals("\r\n", Utility.replaceBareLfWithCrlf("\r\n"));
    114         assertEquals("\r\n", Utility.replaceBareLfWithCrlf("\n"));
    115         assertEquals("\r\n\r\n\r\n", Utility.replaceBareLfWithCrlf("\n\n\n"));
    116         assertEquals("A\r\nB\r\nC\r\nD", Utility.replaceBareLfWithCrlf("A\nB\r\nC\nD"));
    117     }
    118 
    119     public void testGetSmallHash() {
    120         assertEquals("1438642069", Utility.getSmallHash(""));
    121         assertEquals("1354919068", Utility.getSmallHash("abc"));
    122     }
    123 
    124     public void testGetSmallSha1() {
    125         byte[] sha1 = new byte[20];
    126 
    127         // White box test.  Not so great, but to make sure it may detect careless mistakes...
    128         assertEquals(0, Utility.getSmallHashFromSha1(sha1));
    129 
    130         for (int i = 0; i < sha1.length; i++) {
    131             sha1[i] = (byte) 0xFF;
    132         }
    133         assertEquals(Integer.MAX_VALUE, Utility.getSmallHashFromSha1(sha1));
    134 
    135         // Boundary check
    136         for (int i = 0; i < 16; i++) {
    137             sha1[19] = (byte) i;
    138             Utility.getSmallHashFromSha1(sha1);
    139         }
    140     }
    141 
    142     public void brokentestCleanUpMimeDate() {
    143         assertNull(Utility.cleanUpMimeDate(null));
    144         assertEquals("", Utility.cleanUpMimeDate(""));
    145         assertEquals("abc", Utility.cleanUpMimeDate("abc"));
    146         assertEquals("GMT", Utility.cleanUpMimeDate("GMT"));
    147         assertEquals("0000", Utility.cleanUpMimeDate("0000"));
    148         assertEquals("-0000", Utility.cleanUpMimeDate("-0000"));
    149         assertEquals("+1234", Utility.cleanUpMimeDate("GMT+1234"));
    150         assertEquals("-1234", Utility.cleanUpMimeDate("GMT-1234"));
    151         assertEquals("gmt-1234", Utility.cleanUpMimeDate("gmt-1234"));
    152         assertEquals("GMT-123", Utility.cleanUpMimeDate("GMT-123"));
    153 
    154         assertEquals("Thu, 10 Dec 09 15:08:08 -0700",
    155                 Utility.cleanUpMimeDate("Thu, 10 Dec 09 15:08:08 GMT-0700"));
    156         assertEquals("Thu, 10 Dec 09 15:08:08 -0700",
    157                 Utility.cleanUpMimeDate("Thu, 10 Dec 09 15:08:08 -0700"));
    158     }
    159 
    160     private static class MyNewFileCreator implements NewFileCreator {
    161         private final HashSet<String> mExistingFileNames;
    162 
    163         public MyNewFileCreator(String... fileNames) {
    164             mExistingFileNames = new HashSet<String>();
    165             for (String f : fileNames) {
    166                 mExistingFileNames.add(f);
    167             }
    168         }
    169 
    170         @Override public boolean createNewFile(File f) {
    171             return !mExistingFileNames.contains(f.getAbsolutePath());
    172         }
    173     }
    174 
    175     public void testCreateUniqueFile() throws Exception {
    176         final MyNewFileCreator noFiles = new MyNewFileCreator();
    177 
    178         // Case 1: Files don't exist.
    179         checkCreateUniqueFile("/a", noFiles, "/", "a");
    180         checkCreateUniqueFile("/a.txt", noFiles, "/", "a.txt");
    181 
    182         checkCreateUniqueFile("/a/b/a", noFiles, "/a/b", "a");
    183         checkCreateUniqueFile("/a/b/a.txt", noFiles, "/a/b", "a.txt");
    184 
    185         // Case 2: Files exist already.
    186         final MyNewFileCreator files = new MyNewFileCreator(
    187                 "/a", "/a.txt", "/a/b/a", "/a/b/a.txt",
    188                 "/a-2.txt",
    189                 "/a/b/a-2", "/a/b/a-3",
    190                 "/a/b/a-2.txt", "/a/b/a-3.txt", "/a/b/a-4.txt"
    191                 );
    192 
    193         checkCreateUniqueFile("/a-2", files, "/", "a");
    194         checkCreateUniqueFile("/a-3.txt", files, "/", "a.txt");
    195 
    196         checkCreateUniqueFile("/a/b/a-4", files, "/a/b", "a");
    197         checkCreateUniqueFile("/a/b/a-5.txt", files, "/a/b", "a.txt");
    198     }
    199 
    200     private void checkCreateUniqueFile(String expectedFileName, NewFileCreator nfc,
    201             String dir, String fileName) throws Exception {
    202         assertEquals(expectedFileName,
    203                 Utility.createUniqueFileInternal(nfc, new File(dir), fileName).toString());
    204     }
    205 
    206     /**
    207      * Test that we have the necessary permissions to write to external storage.
    208      */
    209     public void testExternalStoragePermissions() throws FileNotFoundException, IOException {
    210         File file = null;
    211         try {
    212             // If there's no storage available, this test is moot
    213             if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
    214                 return;
    215             }
    216             file = Utility.createUniqueFile(Environment.getExternalStorageDirectory(),
    217                     "write-test");
    218             OutputStream out = new FileOutputStream(file);
    219             out.write(1);
    220             out.close();
    221         } finally {
    222             try {
    223                 if (file != null) {
    224                     if (file.exists()) {
    225                         file.delete();
    226                     }
    227                 }
    228             } catch (Exception e) {
    229                 // ignore cleanup error - it still throws the original
    230             }
    231         }
    232     }
    233 
    234     public void testIsPortFieldValid() {
    235         TextView view = new TextView(getContext());
    236         // null, empty, negative, and non integer strings aren't valid
    237         view.setText(null);
    238         assertFalse(Utility.isPortFieldValid(view));
    239         view.setText("");
    240         assertFalse(Utility.isPortFieldValid(view));
    241         view.setText("-1");
    242         assertFalse(Utility.isPortFieldValid(view));
    243         view.setText("1403.75");
    244         assertFalse(Utility.isPortFieldValid(view));
    245         view.setText("0");
    246         assertFalse(Utility.isPortFieldValid(view));
    247         view.setText("65536");
    248         assertFalse(Utility.isPortFieldValid(view));
    249         view.setText("i'm not valid");
    250         assertFalse(Utility.isPortFieldValid(view));
    251         // These next values are valid
    252         view.setText("1");
    253         assertTrue(Utility.isPortFieldValid(view));
    254         view.setText("65535");
    255         assertTrue(Utility.isPortFieldValid(view));
    256     }
    257 
    258     public void testToPrimitiveLongArray() {
    259         assertEquals(0, Utility.toPrimitiveLongArray(createLongCollection()).length);
    260 
    261         final long[] one = Utility.toPrimitiveLongArray(createLongCollection(1));
    262         assertEquals(1, one.length);
    263         assertEquals(1, one[0]);
    264 
    265         final long[] two = Utility.toPrimitiveLongArray(createLongCollection(3, 4));
    266         assertEquals(2, two.length);
    267         assertEquals(3, two[0]);
    268         assertEquals(4, two[1]);
    269     }
    270 
    271     public void testToLongSet() {
    272         assertEquals(0, Utility.toLongSet(new long[] {}).size());
    273 
    274         final Set<Long> one = Utility.toLongSet(new long[] {1});
    275         assertEquals(1, one.size());
    276         assertTrue(one.contains(1L));
    277 
    278         final Set<Long> two = Utility.toLongSet(new long[] {1, 2});
    279         assertEquals(2, two.size());
    280         assertTrue(two.contains(1L));
    281         assertTrue(two.contains(2L));
    282     }
    283 
    284     public void testGetContentFileName() throws Exception {
    285         Context providerContext = DBTestHelper.ProviderContextSetupHelper.getProviderContext(
    286                 mContext);
    287 
    288         final long ACCOUNT_ID = 1;
    289         final long MESSAGE_ID = 10;
    290 
    291         Account account = ProviderTestUtils.setupAccount("account", true, providerContext);
    292         Mailbox mailbox = ProviderTestUtils.setupMailbox("box", account.mId, true, providerContext);
    293 
    294         // Set up an attachment.
    295         Attachment att = ProviderTestUtils.setupAttachment(mailbox.mId, "name", 123, true,
    296                 providerContext);
    297         long attachmentId = att.mId;
    298         Uri uri = AttachmentUtilities.getAttachmentUri(account.mId, attachmentId);
    299 
    300         // Case 1: exists in the provider.
    301         assertEquals("name", Utility.getContentFileName(providerContext, uri));
    302 
    303         // Case 2: doesn't exist in the provider
    304         Uri notExistUri = AttachmentUtilities.getAttachmentUri(account.mId, 123456789);
    305         String lastPathSegment = notExistUri.getLastPathSegment();
    306         assertEquals(lastPathSegment, Utility.getContentFileName(providerContext, notExistUri));
    307     }
    308 
    309     // used by testToPrimitiveLongArray
    310     private static Collection<Long> createLongCollection(long... values) {
    311         ArrayList<Long> ret = new ArrayList<Long>();
    312         for (long value : values) {
    313             ret.add(value);
    314         }
    315         return ret;
    316     }
    317 
    318     public void testDumpCursor() {
    319         // Just make sure the method won't crash and returns non-empty string.
    320         final Cursor c1 = new MatrixCursorWithCachedColumns(new String[] {"col"});
    321         final Cursor c2 = new CursorWrapper(c1);
    322 
    323         // Note it's a subclass of CursorWrapper.
    324         final Cursor c3 = new CursorWrapper(c2) {
    325         };
    326 
    327         assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c1)));
    328         assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c2)));
    329         assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c3)));
    330         assertFalse(TextUtils.isEmpty(Utility.dumpCursor(null)));
    331 
    332         // Test again with closed cursor.
    333         c1.close();
    334         assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c1)));
    335         assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c2)));
    336         assertFalse(TextUtils.isEmpty(Utility.dumpCursor(c3)));
    337         assertFalse(TextUtils.isEmpty(Utility.dumpCursor(null)));
    338     }
    339 
    340     public void testCloseTraceCursorWrapper() {
    341         final Cursor org = new MatrixCursorWithCachedColumns(new String[] {"col"});
    342         final Utility.CloseTraceCursorWrapper c =
    343                 Utility.CloseTraceCursorWrapper.alwaysCreateForTest(org);
    344 
    345         // Not closed -- no stack trace
    346         assertNull(Utility.CloseTraceCursorWrapper.getTraceIfAvailable(c));
    347         Utility.CloseTraceCursorWrapper.log(c); // shouldn't crash
    348 
    349         // Close, now stack trace should be available
    350         c.close();
    351         assertNotNull(Utility.CloseTraceCursorWrapper.getTraceIfAvailable(c));
    352         Utility.CloseTraceCursorWrapper.log(c);
    353 
    354         // shouldn't crash
    355         Utility.CloseTraceCursorWrapper.log(null);
    356     }
    357 
    358     public void brokentestAppendBold() {
    359         SpannableStringBuilder ssb = new SpannableStringBuilder();
    360         ssb.append("no");
    361 
    362         assertEquals(ssb, Utility.appendBold(ssb, "BO"));
    363 
    364         assertEquals("noBO", ssb.toString());
    365         // TODO check style -- but how?
    366     }
    367 
    368     public void testAreStringsEqual() {
    369         String s1;
    370         String s2;
    371 
    372         s1 = new String("Foo");
    373         s2 = s1;
    374         assertTrue(Utility.areStringsEqual(s1, s2));
    375 
    376         s2 = new String("Foo");
    377         assertTrue(Utility.areStringsEqual(s1, s2));
    378 
    379         s2 = "Bar";
    380         assertFalse(Utility.areStringsEqual(s1, s2));
    381 
    382         s2 = null;
    383         assertFalse(Utility.areStringsEqual(s1, s2));
    384 
    385         s1 = null;
    386         s2 = "Bar";
    387         assertFalse(Utility.areStringsEqual(s1, s2));
    388 
    389         s1 = null;
    390         s2 = null;
    391         assertTrue(Utility.areStringsEqual(s1, s2));
    392     }
    393 
    394     public void testIsServerNameValid() {
    395         assertTrue(Utility.isServerNameValid("a"));
    396         assertTrue(Utility.isServerNameValid("gmail"));
    397         assertTrue(Utility.isServerNameValid("gmail.com"));
    398         assertTrue(Utility.isServerNameValid("gmail.com.x.y.z"));
    399         assertTrue(Utility.isServerNameValid("  gmail.com.x.y.z  "));
    400 
    401         assertFalse(Utility.isServerNameValid(""));
    402         assertFalse(Utility.isServerNameValid("$"));
    403         assertFalse(Utility.isServerNameValid("  "));
    404     }
    405 
    406     private static Collection<Long> toColleciton(long... values) {
    407         ArrayList<Long> ret = new ArrayList<Long>();
    408         for (long v : values) {
    409             ret.add(v);
    410         }
    411         return ret;
    412     }
    413 
    414     public void brokentestBuildInSelection() {
    415         assertEquals("", Utility.buildInSelection("c", null));
    416         assertEquals("", Utility.buildInSelection("c", toColleciton()));
    417         assertEquals("c in (1)", Utility.buildInSelection("c", toColleciton(1)));
    418         assertEquals("c in (1,2)", Utility.buildInSelection("c", toColleciton(1, 2)));
    419         assertEquals("c in (1,2,-500)", Utility.buildInSelection("c", toColleciton(1, 2, -500)));
    420     }
    421 }
    422