1f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank/* 2f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * Copyright (C) 2010 The Android Open Source Project 3f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * 4f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * Licensed under the Apache License, Version 2.0 (the "License"); 5f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * you may not use this file except in compliance with the License. 6f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * You may obtain a copy of the License at 7f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * 8f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * http://www.apache.org/licenses/LICENSE-2.0 9f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * 10f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * Unless required by applicable law or agreed to in writing, software 11f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * distributed under the License is distributed on an "AS IS" BASIS, 12f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * See the License for the specific language governing permissions and 14f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank * limitations under the License. 15f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank */ 16f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank 17f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blankpackage com.android.exchange.utility; 18f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank 1989be77eaea65211fea0ca32efd538318c7e049b3Marc Blankimport com.android.email.R; 20befa974de8b74877b2f1ea97e672d3eb2067a6d9Marc Blankimport com.android.email.Utility; 2189be77eaea65211fea0ca32efd538318c7e049b3Marc Blankimport com.android.email.mail.Address; 2289be77eaea65211fea0ca32efd538318c7e049b3Marc Blankimport com.android.email.provider.EmailContent.Account; 2389be77eaea65211fea0ca32efd538318c7e049b3Marc Blankimport com.android.email.provider.EmailContent.Attachment; 2489be77eaea65211fea0ca32efd538318c7e049b3Marc Blankimport com.android.email.provider.EmailContent.Message; 2589be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 2689be77eaea65211fea0ca32efd538318c7e049b3Marc Blankimport android.content.ContentValues; 2789be77eaea65211fea0ca32efd538318c7e049b3Marc Blankimport android.content.Entity; 28bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blankimport android.content.res.Resources; 2989be77eaea65211fea0ca32efd538318c7e049b3Marc Blankimport android.provider.Calendar.Attendees; 3089be77eaea65211fea0ca32efd538318c7e049b3Marc Blankimport android.provider.Calendar.Events; 31f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blankimport android.test.AndroidTestCase; 32aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blankimport android.util.Log; 33f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank 346c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blankimport java.io.BufferedReader; 356c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blankimport java.io.IOException; 366c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blankimport java.io.StringReader; 37bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blankimport java.text.DateFormat; 386c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blankimport java.util.ArrayList; 394006e5fc224d097450fd66a321901b6636f7d9c4Marc Blankimport java.util.Calendar; 404577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blankimport java.util.Date; 414006e5fc224d097450fd66a321901b6636f7d9c4Marc Blankimport java.util.GregorianCalendar; 426c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blankimport java.util.HashMap; 43f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blankimport java.util.TimeZone; 44f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank 456f3013b78708321879728c28db044ab233cb2016Marc Blank/** 466f3013b78708321879728c28db044ab233cb2016Marc Blank * Tests of EAS Calendar Utilities 476f3013b78708321879728c28db044ab233cb2016Marc Blank * You can run this entire test case with: 486f3013b78708321879728c28db044ab233cb2016Marc Blank * runtest -c com.android.exchange.utility.CalendarUtilitiesTests email 496f3013b78708321879728c28db044ab233cb2016Marc Blank * 506f3013b78708321879728c28db044ab233cb2016Marc Blank * Please see RFC2445 for RRULE definition 516f3013b78708321879728c28db044ab233cb2016Marc Blank * http://www.ietf.org/rfc/rfc2445.txt 526f3013b78708321879728c28db044ab233cb2016Marc Blank */ 536f3013b78708321879728c28db044ab233cb2016Marc Blank 54f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blankpublic class CalendarUtilitiesTests extends AndroidTestCase { 55f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank 56f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank // Some prebuilt time zones, Base64 encoded (as they arrive from EAS) 576f3013b78708321879728c28db044ab233cb2016Marc Blank // More time zones to be added over time 586f3013b78708321879728c28db044ab233cb2016Marc Blank 596f3013b78708321879728c28db044ab233cb2016Marc Blank // Not all time zones are appropriate for testing. For example, ISRAEL_STANDARD_TIME cannot be 606f3013b78708321879728c28db044ab233cb2016Marc Blank // used because DST is determined from year to year in a non-standard way (related to the lunar 616f3013b78708321879728c28db044ab233cb2016Marc Blank // calendar); therefore, the test would only work during the year in which it was created 6282b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank 6382b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank // This time zone has no DST 6482b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank private static final String ASIA_CALCUTTA_TIME = 65f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank "tv7//0kAbgBkAGkAYQAgAFMAdABhAG4AZABhAHIAZAAgAFQAaQBtAGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + 66f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEkAbgBkAGkAYQAgAEQAYQB5AGwAaQBnAGgAdAAgAFQAaQBtAGUA" + 67f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; 6882b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank 6982b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank // This time zone is equivalent to PST and uses DST 7082b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank private static final String AMERICA_DAWSON_TIME = 71f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank "4AEAAFAAYQBjAGkAZgBpAGMAIABTAHQAYQBuAGQAYQByAGQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAA" + 72f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank "AAAAAAAAAAsAAAABAAIAAAAAAAAAAAAAAFAAYQBjAGkAZgBpAGMAIABEAGEAeQBsAGkAZwBoAHQAIABUAGkA" + 73f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank "bQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAAAAAAAAAxP///w=="; 74f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank 7582b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank // Test a southern hemisphere time zone w/ DST 7682b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank private static final String AUSTRALIA_ACT_TIME = 7782b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank "qP3//0EAVQBTACAARQBhAHMAdABlAHIAbgAgAFMAdABhAG4AZABhAHIAZAAgAFQAaQBtAGUAAAAAAAAAAAAA" + 7882b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank "AAAAAAAAAAQAAAABAAMAAAAAAAAAAAAAAEEAVQBTACAARQBhAHMAdABlAHIAbgAgAEQAYQB5AGwAaQBnAGgA" + 7982b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank "dAAgAFQAaQBtAGUAAAAAAAAAAAAAAAAAAAAAAAoAAAABAAIAAAAAAAAAxP///w=="; 8082b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank 8182b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank // Test a european time zone w/ DST 8282b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank private static final String EUROPE_MOSCOW_TIME = 8382b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank "TP///1IAdQBzAHMAaQBhAG4AIABTAHQAYQBuAGQAYQByAGQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAA" + 8482b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank "AAAAAAAAAAoAAAAFAAMAAAAAAAAAAAAAAFIAdQBzAHMAaQBhAG4AIABEAGEAeQBsAGkAZwBoAHQAIABUAGkA" + 8582b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank "bQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAAIAAAAAAAAAxP///w=="; 8682b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank 873e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank // Test a timezone with GMT bias but bogus DST parameters (there is no equivalent time zone 883e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank // in the database) 893e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank private static final String GMT_UNKNOWN_DAYLIGHT_TIME = 903e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank "AAAAACgARwBNAFQAKwAwADAAOgAwADAAKQAgAFQAaQBtAGUAIABaAG8AbgBlAAAAAAAAAAAAAAAAAAAAAAAA" + 913e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank "AAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAACgARwBNAFQAKwAwADAAOgAwADAAKQAgAFQAaQBtAGUAIABaAG8A" + 923e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank "bgBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAFAAEAAAAAAAAAxP///w=="; 933e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank 94c55e2c884743bf5dee7de8d0fda69db3510476fdMarc Blank // This time zone has no DST, but earlier, buggy code retrieved a TZ WITH DST 95c55e2c884743bf5dee7de8d0fda69db3510476fdMarc Blank private static final String ARIZONA_TIME = 96c55e2c884743bf5dee7de8d0fda69db3510476fdMarc Blank "pAEAAFUAUwAgAE0AbwB1AG4AdABhAGkAbgAgAFMAdABhAG4AZABhAHIAZAAgAFQAaQBtAGUAAAAAAAAAAAAA" + 97c55e2c884743bf5dee7de8d0fda69db3510476fdMarc Blank "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFUAUwAgAE0AbwB1AG4AdABhAGkAbgAgAEQAYQB5AGwAaQBnAGgA" + 98c55e2c884743bf5dee7de8d0fda69db3510476fdMarc Blank "dAAgAFQAaQBtAGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; 99c55e2c884743bf5dee7de8d0fda69db3510476fdMarc Blank 100bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank private static final String ORGANIZER = "organizer@server.com"; 101bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank private static final String ATTENDEE = "attendee@server.com"; 102bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank 103f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank public void testGetSet() { 104f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7}; 105f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank 106f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank // First, check that getWord/Long are properly little endian 107f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank assertEquals(0x0100, CalendarUtilities.getWord(bytes, 0)); 108f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank assertEquals(0x03020100, CalendarUtilities.getLong(bytes, 0)); 109f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank assertEquals(0x07060504, CalendarUtilities.getLong(bytes, 4)); 110f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank 111f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank // Set some words and longs 112f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank CalendarUtilities.setWord(bytes, 0, 0xDEAD); 113f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank CalendarUtilities.setLong(bytes, 2, 0xBEEFBEEF); 114f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank CalendarUtilities.setWord(bytes, 6, 0xCEDE); 115f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank 116f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank // Retrieve them 117f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank assertEquals(0xDEAD, CalendarUtilities.getWord(bytes, 0)); 118f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank assertEquals(0xBEEFBEEF, CalendarUtilities.getLong(bytes, 2)); 119f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank assertEquals(0xCEDE, CalendarUtilities.getWord(bytes, 6)); 120f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank } 121f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank 122f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank public void testParseTimeZoneEndToEnd() { 12382b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank TimeZone tz = CalendarUtilities.tziStringToTimeZone(AMERICA_DAWSON_TIME); 12482b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank assertEquals("America/Dawson", tz.getID()); 12582b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank tz = CalendarUtilities.tziStringToTimeZone(ASIA_CALCUTTA_TIME); 12682b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank assertEquals("Asia/Calcutta", tz.getID()); 12782b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank tz = CalendarUtilities.tziStringToTimeZone(AUSTRALIA_ACT_TIME); 12882b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank assertEquals("Australia/ACT", tz.getID()); 12982b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank tz = CalendarUtilities.tziStringToTimeZone(EUROPE_MOSCOW_TIME); 13082b2453b97c69d3cab169a7c00e4c410006ee068Marc Blank assertEquals("Europe/Moscow", tz.getID()); 1313e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank tz = CalendarUtilities.tziStringToTimeZone(GMT_UNKNOWN_DAYLIGHT_TIME); 1323e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank int bias = tz.getOffset(System.currentTimeMillis()); 1333e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank assertEquals(0, bias); 134c55e2c884743bf5dee7de8d0fda69db3510476fdMarc Blank // Make sure non-DST TZ's work properly 135c55e2c884743bf5dee7de8d0fda69db3510476fdMarc Blank tz = CalendarUtilities.tziStringToTimeZone(ARIZONA_TIME); 136c55e2c884743bf5dee7de8d0fda69db3510476fdMarc Blank assertEquals("America/Phoenix", tz.getID()); 137f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank } 138f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank 139a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank public void testGenerateEasDayOfWeek() { 140befa974de8b74877b2f1ea97e672d3eb2067a6d9Marc Blank String byDay = "TU,WE,SA"; 1416f3013b78708321879728c28db044ab233cb2016Marc Blank // TU = 4, WE = 8; SA = 64; 142a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank assertEquals("76", CalendarUtilities.generateEasDayOfWeek(byDay)); 1436f3013b78708321879728c28db044ab233cb2016Marc Blank // MO = 2, TU = 4; WE = 8; TH = 16; FR = 32 144befa974de8b74877b2f1ea97e672d3eb2067a6d9Marc Blank byDay = "MO,TU,WE,TH,FR"; 145a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank assertEquals("62", CalendarUtilities.generateEasDayOfWeek(byDay)); 1466f3013b78708321879728c28db044ab233cb2016Marc Blank // SU = 1 147a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank byDay = "SU"; 148a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank assertEquals("1", CalendarUtilities.generateEasDayOfWeek(byDay)); 149a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank } 150a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank 151a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank public void testTokenFromRrule() { 152a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank String rrule = "FREQ=DAILY;INTERVAL=1;BYDAY=WE,TH,SA;BYMONTHDAY=17"; 153a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank assertEquals("DAILY", CalendarUtilities.tokenFromRrule(rrule, "FREQ=")); 154a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank assertEquals("1", CalendarUtilities.tokenFromRrule(rrule, "INTERVAL=")); 155a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank assertEquals("17", CalendarUtilities.tokenFromRrule(rrule, "BYMONTHDAY=")); 156befa974de8b74877b2f1ea97e672d3eb2067a6d9Marc Blank assertEquals("WE,TH,SA", CalendarUtilities.tokenFromRrule(rrule, "BYDAY=")); 157a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank assertNull(CalendarUtilities.tokenFromRrule(rrule, "UNTIL=")); 158a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank } 159a8259394596eda7aed2b9edfdb30ff03c34acb66Marc Blank 160cf7581c51c39aad1e8e955bfde62335871a7fd29Marc Blank public void testRecurrenceUntilToEasUntil() { 161cf274512ed722cd039e21ab05ce172052740116fMarc Blank // Test full format 162cf274512ed722cd039e21ab05ce172052740116fMarc Blank assertEquals("YYYYMMDDT000000Z", 163cf7581c51c39aad1e8e955bfde62335871a7fd29Marc Blank CalendarUtilities.recurrenceUntilToEasUntil("YYYYMMDDTHHMMSSZ")); 164cf7581c51c39aad1e8e955bfde62335871a7fd29Marc Blank // Test date only format 165cf274512ed722cd039e21ab05ce172052740116fMarc Blank assertEquals("YYYYMMDDT000000Z", 166cf7581c51c39aad1e8e955bfde62335871a7fd29Marc Blank CalendarUtilities.recurrenceUntilToEasUntil("YYYYMMDD")); 167cf7581c51c39aad1e8e955bfde62335871a7fd29Marc Blank } 168cf7581c51c39aad1e8e955bfde62335871a7fd29Marc Blank 1694006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank public void testParseEmailDateTimeToMillis(String date) { 1704006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank // Format for email date strings is 2010-02-23T16:00:00.000Z 1714006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank String dateString = "2010-02-23T15:16:17.000Z"; 172989552c10744e2d7f8fca1bdb2baef5273a8a0b9Mihai Preda long dateTime = Utility.parseEmailDateTimeToMillis(dateString); 1734006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank GregorianCalendar cal = new GregorianCalendar(); 1744006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank cal.setTimeInMillis(dateTime); 1754006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank cal.setTimeZone(TimeZone.getTimeZone("GMT")); 1764006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.YEAR), 2010); 1774006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.MONTH), 1); // 0 based 1784006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.DAY_OF_MONTH), 23); 1794006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.HOUR_OF_DAY), 16); 1804006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.MINUTE), 16); 1814006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.SECOND), 17); 1824006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank } 1834006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank 1844006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank public void testParseDateTimeToMillis(String date) { 1854006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank // Format for calendar date strings is 20100223T160000000Z 1864006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank String dateString = "20100223T151617000Z"; 187989552c10744e2d7f8fca1bdb2baef5273a8a0b9Mihai Preda long dateTime = Utility.parseDateTimeToMillis(dateString); 1884006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank GregorianCalendar cal = new GregorianCalendar(); 1894006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank cal.setTimeInMillis(dateTime); 1904006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank cal.setTimeZone(TimeZone.getTimeZone("GMT")); 1914006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.YEAR), 2010); 1924006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.MONTH), 1); // 0 based 1934006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.DAY_OF_MONTH), 23); 1944006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.HOUR_OF_DAY), 16); 1954006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.MINUTE), 16); 1964006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank assertEquals(cal.get(Calendar.SECOND), 17); 1974006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank } 198cf7581c51c39aad1e8e955bfde62335871a7fd29Marc Blank 1996c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank private Entity setupTestEventEntity(String organizer, String attendee, String title) { 20089be77eaea65211fea0ca32efd538318c7e049b3Marc Blank // Create an Entity for an Event 20189be77eaea65211fea0ca32efd538318c7e049b3Marc Blank ContentValues entityValues = new ContentValues(); 20289be77eaea65211fea0ca32efd538318c7e049b3Marc Blank Entity entity = new Entity(entityValues); 20389be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 20489be77eaea65211fea0ca32efd538318c7e049b3Marc Blank // Set up values for the Event 20589be77eaea65211fea0ca32efd538318c7e049b3Marc Blank String location = "Meeting Location"; 20689be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 20789be77eaea65211fea0ca32efd538318c7e049b3Marc Blank // Fill in times, location, title, and organizer 20889be77eaea65211fea0ca32efd538318c7e049b3Marc Blank entityValues.put("DTSTAMP", 20989be77eaea65211fea0ca32efd538318c7e049b3Marc Blank CalendarUtilities.convertEmailDateTimeToCalendarDateTime("2010-04-05T14:30:51Z")); 21089be77eaea65211fea0ca32efd538318c7e049b3Marc Blank entityValues.put(Events.DTSTART, 211989552c10744e2d7f8fca1bdb2baef5273a8a0b9Mihai Preda Utility.parseEmailDateTimeToMillis("2010-04-12T18:30:00Z")); 21289be77eaea65211fea0ca32efd538318c7e049b3Marc Blank entityValues.put(Events.DTEND, 213989552c10744e2d7f8fca1bdb2baef5273a8a0b9Mihai Preda Utility.parseEmailDateTimeToMillis("2010-04-12T19:30:00Z")); 21489be77eaea65211fea0ca32efd538318c7e049b3Marc Blank entityValues.put(Events.EVENT_LOCATION, location); 21589be77eaea65211fea0ca32efd538318c7e049b3Marc Blank entityValues.put(Events.TITLE, title); 21689be77eaea65211fea0ca32efd538318c7e049b3Marc Blank entityValues.put(Events.ORGANIZER, organizer); 2176c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank entityValues.put(Events._SYNC_DATA, "31415926535"); 21889be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 21989be77eaea65211fea0ca32efd538318c7e049b3Marc Blank // Add the attendee 22089be77eaea65211fea0ca32efd538318c7e049b3Marc Blank ContentValues attendeeValues = new ContentValues(); 22189be77eaea65211fea0ca32efd538318c7e049b3Marc Blank attendeeValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE); 22289be77eaea65211fea0ca32efd538318c7e049b3Marc Blank attendeeValues.put(Attendees.ATTENDEE_EMAIL, attendee); 22389be77eaea65211fea0ca32efd538318c7e049b3Marc Blank entity.addSubValue(Attendees.CONTENT_URI, attendeeValues); 22489be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 22589be77eaea65211fea0ca32efd538318c7e049b3Marc Blank // Add the organizer 22689be77eaea65211fea0ca32efd538318c7e049b3Marc Blank ContentValues organizerValues = new ContentValues(); 22789be77eaea65211fea0ca32efd538318c7e049b3Marc Blank organizerValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ORGANIZER); 22889be77eaea65211fea0ca32efd538318c7e049b3Marc Blank organizerValues.put(Attendees.ATTENDEE_EMAIL, organizer); 22989be77eaea65211fea0ca32efd538318c7e049b3Marc Blank entity.addSubValue(Attendees.CONTENT_URI, organizerValues); 2306c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank return entity; 2316c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 23289be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 23382e51e06312c76f37900c7b1718af863caeff9afMarc Blank private Entity setupTestExceptionEntity(String organizer, String attendee, String title) { 23482e51e06312c76f37900c7b1718af863caeff9afMarc Blank Entity entity = setupTestEventEntity(organizer, attendee, title); 23582e51e06312c76f37900c7b1718af863caeff9afMarc Blank ContentValues entityValues = entity.getEntityValues(); 23682e51e06312c76f37900c7b1718af863caeff9afMarc Blank entityValues.put(Events.ORIGINAL_EVENT, 69); 23782e51e06312c76f37900c7b1718af863caeff9afMarc Blank // The exception will be on April 26th 23882e51e06312c76f37900c7b1718af863caeff9afMarc Blank entityValues.put(Events.ORIGINAL_INSTANCE_TIME, 23982e51e06312c76f37900c7b1718af863caeff9afMarc Blank Utility.parseEmailDateTimeToMillis("2010-04-26T18:30:00Z")); 24082e51e06312c76f37900c7b1718af863caeff9afMarc Blank return entity; 24182e51e06312c76f37900c7b1718af863caeff9afMarc Blank } 24282e51e06312c76f37900c7b1718af863caeff9afMarc Blank 2436c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank public void testCreateMessageForEntity_Reply() { 2446c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Set up the "event" 2456c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank String title = "Discuss Unit Tests"; 246bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title); 24789be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 2486c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Create a dummy account for the attendee 2496c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank Account account = new Account(); 250bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank account.mEmailAddress = ATTENDEE; 25189be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 2526c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // The uid is required, but can be anything 2536c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank String uid = "31415926535"; 2546c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 25589be77eaea65211fea0ca32efd538318c7e049b3Marc Blank // Create the outgoing message 25689be77eaea65211fea0ca32efd538318c7e049b3Marc Blank Message msg = CalendarUtilities.createMessageForEntity(mContext, entity, 25789be77eaea65211fea0ca32efd538318c7e049b3Marc Blank Message.FLAG_OUTGOING_MEETING_ACCEPT, uid, account); 25889be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 25989be77eaea65211fea0ca32efd538318c7e049b3Marc Blank // First, we should have a message 26089be77eaea65211fea0ca32efd538318c7e049b3Marc Blank assertNotNull(msg); 26189be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 26289be77eaea65211fea0ca32efd538318c7e049b3Marc Blank // Now check some of the fields of the message 263bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank assertEquals(Address.pack(new Address[] {new Address(ORGANIZER)}), msg.mTo); 264a6e1f8d4562ed437d67378935c8be6cbfe9b86f9Marc Blank Resources resources = getContext().getResources(); 265a6e1f8d4562ed437d67378935c8be6cbfe9b86f9Marc Blank String accept = resources.getString(R.string.meeting_accepted, title); 2664577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertEquals(accept, msg.mSubject); 267a6e1f8d4562ed437d67378935c8be6cbfe9b86f9Marc Blank assertNotNull(msg.mText); 268a6e1f8d4562ed437d67378935c8be6cbfe9b86f9Marc Blank assertTrue(msg.mText.contains(resources.getString(R.string.meeting_where, ""))); 26989be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 27089be77eaea65211fea0ca32efd538318c7e049b3Marc Blank // And make sure we have an attachment 27189be77eaea65211fea0ca32efd538318c7e049b3Marc Blank assertNotNull(msg.mAttachments); 27289be77eaea65211fea0ca32efd538318c7e049b3Marc Blank assertEquals(1, msg.mAttachments.size()); 27389be77eaea65211fea0ca32efd538318c7e049b3Marc Blank Attachment att = msg.mAttachments.get(0); 27489be77eaea65211fea0ca32efd538318c7e049b3Marc Blank // And that the attachment has the correct elements 27589be77eaea65211fea0ca32efd538318c7e049b3Marc Blank assertEquals("invite.ics", att.mFileName); 2760ed690bfb4fdfa86cb6f75c19e24b8ff39a1756cMarc Blank assertEquals(Attachment.FLAG_ICS_ALTERNATIVE_PART, 2770ed690bfb4fdfa86cb6f75c19e24b8ff39a1756cMarc Blank att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART); 27889be77eaea65211fea0ca32efd538318c7e049b3Marc Blank assertEquals("text/calendar; method=REPLY", att.mMimeType); 27920225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki assertNotNull(att.mContentBytes); 28020225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki assertEquals(att.mSize, att.mContentBytes.length); 28189be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 28289be77eaea65211fea0ca32efd538318c7e049b3Marc Blank //TODO Check the contents of the attachment using an iCalendar parser 28389be77eaea65211fea0ca32efd538318c7e049b3Marc Blank } 28489be77eaea65211fea0ca32efd538318c7e049b3Marc Blank 2851c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank public void testCreateMessageForEntity_Invite_AllDay() throws IOException { 2861c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // Set up the "event" 2871c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank String title = "Discuss Unit Tests"; 2881c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title); 2891c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank entity.getEntityValues().put(Events.ALL_DAY, 1); 2901c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 2911c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // Create a dummy account for the attendee 2921c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank Account account = new Account(); 2931c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank account.mEmailAddress = ORGANIZER; 2941c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 2951c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // The uid is required, but can be anything 2961c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank String uid = "31415926535"; 2971c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 2981c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // Create the outgoing message 2991c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank Message msg = CalendarUtilities.createMessageForEntity(mContext, entity, 3001c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank Message.FLAG_OUTGOING_MEETING_INVITE, uid, account); 3011c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 3021c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // First, we should have a message 3031c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertNotNull(msg); 3041c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 3051c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // Now check some of the fields of the message 3061c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals(Address.pack(new Address[] {new Address(ATTENDEE)}), msg.mTo); 30778021cbbf8154898ce4e68d8c2d2871568cda5e3Marc Blank assertEquals(title, msg.mSubject); 3081c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 3091c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // And make sure we have an attachment 3101c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertNotNull(msg.mAttachments); 3111c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals(1, msg.mAttachments.size()); 3121c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank Attachment att = msg.mAttachments.get(0); 3131c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // And that the attachment has the correct elements 3141c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("invite.ics", att.mFileName); 3151c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals(Attachment.FLAG_ICS_ALTERNATIVE_PART, 3161c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART); 3171c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("text/calendar; method=REQUEST", att.mMimeType); 3181c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertNotNull(att.mContentBytes); 3191c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals(att.mSize, att.mContentBytes.length); 3201c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 3211c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // We'll check the contents of the ics file here 3221c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank BlockHash vcalendar = parseIcsContent(att.mContentBytes); 3231c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertNotNull(vcalendar); 3241c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 3251c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // We should have a VCALENDAR with a REQUEST method 3261c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("VCALENDAR", vcalendar.name); 3271c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("REQUEST", vcalendar.get("METHOD")); 3281c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 3291c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // We should have one block under VCALENDAR 3301c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals(1, vcalendar.blocks.size()); 3311c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank BlockHash vevent = vcalendar.blocks.get(0); 3321c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // It's a VEVENT with the following fields 3331c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("VEVENT", vevent.name); 3341c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("Meeting Location", vevent.get("LOCATION")); 3351c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("0", vevent.get("SEQUENCE")); 3361c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("Discuss Unit Tests", vevent.get("SUMMARY")); 3371c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals(uid, vevent.get("UID")); 3381c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("MAILTO:" + ATTENDEE, 3391c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank vevent.get("ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE")); 3401c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 3411c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // These next two fields should have a date only 3421c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("20100412", vevent.get("DTSTART;VALUE=DATE")); 3431c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("20100412", vevent.get("DTEND;VALUE=DATE")); 3441c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // This should be set to TRUE for all-day events 3451c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals("TRUE", vevent.get("X-MICROSOFT-CDO-ALLDAYEVENT")); 3461c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank } 3471c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 3486c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank public void testCreateMessageForEntity_Invite() throws IOException { 3496c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Set up the "event" 3506c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank String title = "Discuss Unit Tests"; 351bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title); 3526c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 3536c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Create a dummy account for the attendee 3546c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank Account account = new Account(); 355bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank account.mEmailAddress = ORGANIZER; 3566c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 3576c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // The uid is required, but can be anything 3586c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank String uid = "31415926535"; 3596c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 3606c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Create the outgoing message 3616c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank Message msg = CalendarUtilities.createMessageForEntity(mContext, entity, 3626c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank Message.FLAG_OUTGOING_MEETING_INVITE, uid, account); 3636c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 3646c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // First, we should have a message 3656c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertNotNull(msg); 3666c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 3676c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Now check some of the fields of the message 368bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank assertEquals(Address.pack(new Address[] {new Address(ATTENDEE)}), msg.mTo); 36978021cbbf8154898ce4e68d8c2d2871568cda5e3Marc Blank assertEquals(title, msg.mSubject); 3706c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 3716c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // And make sure we have an attachment 3726c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertNotNull(msg.mAttachments); 3736c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertEquals(1, msg.mAttachments.size()); 3746c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank Attachment att = msg.mAttachments.get(0); 3756c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // And that the attachment has the correct elements 3766c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertEquals("invite.ics", att.mFileName); 3770ed690bfb4fdfa86cb6f75c19e24b8ff39a1756cMarc Blank assertEquals(Attachment.FLAG_ICS_ALTERNATIVE_PART, 3780ed690bfb4fdfa86cb6f75c19e24b8ff39a1756cMarc Blank att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART); 3796c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertEquals("text/calendar; method=REQUEST", att.mMimeType); 38020225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki assertNotNull(att.mContentBytes); 38120225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki assertEquals(att.mSize, att.mContentBytes.length); 3826c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 3836c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // We'll check the contents of the ics file here 38420225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki BlockHash vcalendar = parseIcsContent(att.mContentBytes); 3856c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertNotNull(vcalendar); 3866c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 3876c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // We should have a VCALENDAR with a REQUEST method 3886c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertEquals("VCALENDAR", vcalendar.name); 3896c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertEquals("REQUEST", vcalendar.get("METHOD")); 3906c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 3916c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // We should have one block under VCALENDAR 3926c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertEquals(1, vcalendar.blocks.size()); 3936c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank BlockHash vevent = vcalendar.blocks.get(0); 3946c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // It's a VEVENT with the following fields 3956c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertEquals("VEVENT", vevent.name); 3966c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertEquals("Meeting Location", vevent.get("LOCATION")); 3976c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertEquals("0", vevent.get("SEQUENCE")); 3986c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertEquals("Discuss Unit Tests", vevent.get("SUMMARY")); 3996c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank assertEquals(uid, vevent.get("UID")); 400bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank assertEquals("MAILTO:" + ATTENDEE, 4016c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank vevent.get("ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE")); 4021c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank 4031c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // These next two fields should exist (without the VALUE=DATE suffix) 4041c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertNotNull(vevent.get("DTSTART")); 4051c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertNotNull(vevent.get("DTEND")); 4061c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertNull(vevent.get("DTSTART;VALUE=DATE")); 4071c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertNull(vevent.get("DTEND;VALUE=DATE")); 4081c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank // This shouldn't exist for this event 4091c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertNull(vevent.get("X-MICROSOFT-CDO-ALLDAYEVENT")); 4106c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 4116c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 4129294d8c030039070d173acb9907b64a48d4b165fMarc Blank public void testCreateMessageForEntity_Recurring() throws IOException { 4139294d8c030039070d173acb9907b64a48d4b165fMarc Blank // Set up the "event" 4149294d8c030039070d173acb9907b64a48d4b165fMarc Blank String title = "Discuss Unit Tests"; 4159294d8c030039070d173acb9907b64a48d4b165fMarc Blank Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title); 4169294d8c030039070d173acb9907b64a48d4b165fMarc Blank // Set up a RRULE for this event 4179294d8c030039070d173acb9907b64a48d4b165fMarc Blank entity.getEntityValues().put(Events.RRULE, "FREQ=DAILY"); 4189294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4199294d8c030039070d173acb9907b64a48d4b165fMarc Blank // Create a dummy account for the attendee 4209294d8c030039070d173acb9907b64a48d4b165fMarc Blank Account account = new Account(); 4219294d8c030039070d173acb9907b64a48d4b165fMarc Blank account.mEmailAddress = ORGANIZER; 4229294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4239294d8c030039070d173acb9907b64a48d4b165fMarc Blank // The uid is required, but can be anything 4249294d8c030039070d173acb9907b64a48d4b165fMarc Blank String uid = "31415926535"; 4259294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4269294d8c030039070d173acb9907b64a48d4b165fMarc Blank // Create the outgoing message 4279294d8c030039070d173acb9907b64a48d4b165fMarc Blank Message msg = CalendarUtilities.createMessageForEntity(mContext, entity, 4289294d8c030039070d173acb9907b64a48d4b165fMarc Blank Message.FLAG_OUTGOING_MEETING_INVITE, uid, account); 4299294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4309294d8c030039070d173acb9907b64a48d4b165fMarc Blank // First, we should have a message 4319294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertNotNull(msg); 4329294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4339294d8c030039070d173acb9907b64a48d4b165fMarc Blank // Now check some of the fields of the message 4349294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals(Address.pack(new Address[] {new Address(ATTENDEE)}), msg.mTo); 4359294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals(title, msg.mSubject); 4369294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4379294d8c030039070d173acb9907b64a48d4b165fMarc Blank // And make sure we have an attachment 4389294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertNotNull(msg.mAttachments); 4399294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals(1, msg.mAttachments.size()); 4409294d8c030039070d173acb9907b64a48d4b165fMarc Blank Attachment att = msg.mAttachments.get(0); 4419294d8c030039070d173acb9907b64a48d4b165fMarc Blank // And that the attachment has the correct elements 4429294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals("invite.ics", att.mFileName); 4439294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals(Attachment.FLAG_ICS_ALTERNATIVE_PART, 4449294d8c030039070d173acb9907b64a48d4b165fMarc Blank att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART); 4459294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals("text/calendar; method=REQUEST", att.mMimeType); 4469294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertNotNull(att.mContentBytes); 4479294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals(att.mSize, att.mContentBytes.length); 4489294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4499294d8c030039070d173acb9907b64a48d4b165fMarc Blank // We'll check the contents of the ics file here 4509294d8c030039070d173acb9907b64a48d4b165fMarc Blank BlockHash vcalendar = parseIcsContent(att.mContentBytes); 4519294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertNotNull(vcalendar); 4529294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4539294d8c030039070d173acb9907b64a48d4b165fMarc Blank // We should have a VCALENDAR with a REQUEST method 4549294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals("VCALENDAR", vcalendar.name); 4559294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals("REQUEST", vcalendar.get("METHOD")); 4569294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4579294d8c030039070d173acb9907b64a48d4b165fMarc Blank // We should have two blocks under VCALENDAR (VTIMEZONE and VEVENT) 4589294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals(2, vcalendar.blocks.size()); 4599294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4609294d8c030039070d173acb9907b64a48d4b165fMarc Blank // This is the time zone that should be used 4619294d8c030039070d173acb9907b64a48d4b165fMarc Blank TimeZone timeZone = TimeZone.getDefault(); 4629294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4639294d8c030039070d173acb9907b64a48d4b165fMarc Blank BlockHash vtimezone = vcalendar.blocks.get(0); 4649294d8c030039070d173acb9907b64a48d4b165fMarc Blank // It should be a VTIMEZONE for timeZone 4659294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals("VTIMEZONE", vtimezone.name); 4669294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals(timeZone.getID(), vtimezone.get("TZID")); 4679294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4689294d8c030039070d173acb9907b64a48d4b165fMarc Blank BlockHash vevent = vcalendar.blocks.get(1); 4699294d8c030039070d173acb9907b64a48d4b165fMarc Blank // It's a VEVENT with the following fields 4709294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals("VEVENT", vevent.name); 4719294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals("Meeting Location", vevent.get("LOCATION")); 4729294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals("0", vevent.get("SEQUENCE")); 4739294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals("Discuss Unit Tests", vevent.get("SUMMARY")); 4749294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals(uid, vevent.get("UID")); 4759294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertEquals("MAILTO:" + ATTENDEE, 4769294d8c030039070d173acb9907b64a48d4b165fMarc Blank vevent.get("ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE")); 4779294d8c030039070d173acb9907b64a48d4b165fMarc Blank 4789294d8c030039070d173acb9907b64a48d4b165fMarc Blank // We should have DTSTART/DTEND with time zone 4799294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertNotNull(vevent.get("DTSTART;TZID=" + timeZone.getID())); 4809294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertNotNull(vevent.get("DTEND;TZID=" + timeZone.getID())); 4819294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertNull(vevent.get("DTSTART")); 4829294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertNull(vevent.get("DTEND")); 4839294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertNull(vevent.get("DTSTART;VALUE=DATE")); 4849294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertNull(vevent.get("DTEND;VALUE=DATE")); 4859294d8c030039070d173acb9907b64a48d4b165fMarc Blank // This shouldn't exist for this event 4869294d8c030039070d173acb9907b64a48d4b165fMarc Blank assertNull(vevent.get("X-MICROSOFT-CDO-ALLDAYEVENT")); 4879294d8c030039070d173acb9907b64a48d4b165fMarc Blank } 4889294d8c030039070d173acb9907b64a48d4b165fMarc Blank 48982e51e06312c76f37900c7b1718af863caeff9afMarc Blank public void testCreateMessageForEntity_Exception_Cancel() throws IOException { 49082e51e06312c76f37900c7b1718af863caeff9afMarc Blank // Set up the "exception"... 49182e51e06312c76f37900c7b1718af863caeff9afMarc Blank String title = "Discuss Unit Tests"; 492bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank Entity entity = setupTestExceptionEntity(ORGANIZER, ATTENDEE, title); 49382e51e06312c76f37900c7b1718af863caeff9afMarc Blank 49482e51e06312c76f37900c7b1718af863caeff9afMarc Blank ContentValues entityValues = entity.getEntityValues(); 49582e51e06312c76f37900c7b1718af863caeff9afMarc Blank // Mark the Exception as dirty 49682e51e06312c76f37900c7b1718af863caeff9afMarc Blank entityValues.put(Events._SYNC_DIRTY, 1); 49782e51e06312c76f37900c7b1718af863caeff9afMarc Blank // And mark it canceled 49882e51e06312c76f37900c7b1718af863caeff9afMarc Blank entityValues.put(Events.STATUS, Events.STATUS_CANCELED); 49982e51e06312c76f37900c7b1718af863caeff9afMarc Blank 50082e51e06312c76f37900c7b1718af863caeff9afMarc Blank // Create a dummy account for the attendee 50182e51e06312c76f37900c7b1718af863caeff9afMarc Blank Account account = new Account(); 502bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank account.mEmailAddress = ORGANIZER; 50382e51e06312c76f37900c7b1718af863caeff9afMarc Blank 50482e51e06312c76f37900c7b1718af863caeff9afMarc Blank // The uid is required, but can be anything 50582e51e06312c76f37900c7b1718af863caeff9afMarc Blank String uid = "31415926535"; 50682e51e06312c76f37900c7b1718af863caeff9afMarc Blank 50782e51e06312c76f37900c7b1718af863caeff9afMarc Blank // Create the outgoing message 50882e51e06312c76f37900c7b1718af863caeff9afMarc Blank Message msg = CalendarUtilities.createMessageForEntity(mContext, entity, 50939ea302126b6d205ae561a9c3f568b75aa6a202aMarc Blank Message.FLAG_OUTGOING_MEETING_CANCEL, uid, account); 51082e51e06312c76f37900c7b1718af863caeff9afMarc Blank 51182e51e06312c76f37900c7b1718af863caeff9afMarc Blank // First, we should have a message 51282e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertNotNull(msg); 51382e51e06312c76f37900c7b1718af863caeff9afMarc Blank 51482e51e06312c76f37900c7b1718af863caeff9afMarc Blank // Now check some of the fields of the message 515bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank assertEquals(Address.pack(new Address[] {new Address(ATTENDEE)}), msg.mTo); 51639ea302126b6d205ae561a9c3f568b75aa6a202aMarc Blank String cancel = getContext().getResources().getString(R.string.meeting_canceled, title); 51739ea302126b6d205ae561a9c3f568b75aa6a202aMarc Blank assertEquals(cancel, msg.mSubject); 51882e51e06312c76f37900c7b1718af863caeff9afMarc Blank 51982e51e06312c76f37900c7b1718af863caeff9afMarc Blank // And make sure we have an attachment 52082e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertNotNull(msg.mAttachments); 52182e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertEquals(1, msg.mAttachments.size()); 52282e51e06312c76f37900c7b1718af863caeff9afMarc Blank Attachment att = msg.mAttachments.get(0); 52382e51e06312c76f37900c7b1718af863caeff9afMarc Blank // And that the attachment has the correct elements 52482e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertEquals("invite.ics", att.mFileName); 5250ed690bfb4fdfa86cb6f75c19e24b8ff39a1756cMarc Blank assertEquals(Attachment.FLAG_ICS_ALTERNATIVE_PART, 5260ed690bfb4fdfa86cb6f75c19e24b8ff39a1756cMarc Blank att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART); 527700b373007da10b456e1f9cb0fde2a021fdee84cMarc Blank assertEquals("text/calendar; method=CANCEL", att.mMimeType); 52820225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki assertNotNull(att.mContentBytes); 52982e51e06312c76f37900c7b1718af863caeff9afMarc Blank 53082e51e06312c76f37900c7b1718af863caeff9afMarc Blank // We'll check the contents of the ics file here 53120225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki BlockHash vcalendar = parseIcsContent(att.mContentBytes); 53282e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertNotNull(vcalendar); 53382e51e06312c76f37900c7b1718af863caeff9afMarc Blank 534700b373007da10b456e1f9cb0fde2a021fdee84cMarc Blank // We should have a VCALENDAR with a CANCEL method 53582e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertEquals("VCALENDAR", vcalendar.name); 536700b373007da10b456e1f9cb0fde2a021fdee84cMarc Blank assertEquals("CANCEL", vcalendar.get("METHOD")); 53782e51e06312c76f37900c7b1718af863caeff9afMarc Blank 53882e51e06312c76f37900c7b1718af863caeff9afMarc Blank // This is the time zone that should be used 53982e51e06312c76f37900c7b1718af863caeff9afMarc Blank TimeZone timeZone = TimeZone.getDefault(); 54082e51e06312c76f37900c7b1718af863caeff9afMarc Blank 54182e51e06312c76f37900c7b1718af863caeff9afMarc Blank // We should have two blocks under VCALENDAR (VTIMEZONE and VEVENT) 54282e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertEquals(2, vcalendar.blocks.size()); 54382e51e06312c76f37900c7b1718af863caeff9afMarc Blank 54482e51e06312c76f37900c7b1718af863caeff9afMarc Blank BlockHash vtimezone = vcalendar.blocks.get(0); 54582e51e06312c76f37900c7b1718af863caeff9afMarc Blank // It should be a VTIMEZONE for timeZone 54682e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertEquals("VTIMEZONE", vtimezone.name); 54782e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertEquals(timeZone.getID(), vtimezone.get("TZID")); 54882e51e06312c76f37900c7b1718af863caeff9afMarc Blank 54982e51e06312c76f37900c7b1718af863caeff9afMarc Blank BlockHash vevent = vcalendar.blocks.get(1); 55082e51e06312c76f37900c7b1718af863caeff9afMarc Blank // It's a VEVENT with the following fields 55182e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertEquals("VEVENT", vevent.name); 55282e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertEquals("Meeting Location", vevent.get("LOCATION")); 55382e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertEquals("0", vevent.get("SEQUENCE")); 55482e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertEquals("Discuss Unit Tests", vevent.get("SUMMARY")); 55582e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertEquals(uid, vevent.get("UID")); 556bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank assertEquals("MAILTO:" + ATTENDEE, 55739ea302126b6d205ae561a9c3f568b75aa6a202aMarc Blank vevent.get("ATTENDEE;ROLE=REQ-PARTICIPANT")); 55882e51e06312c76f37900c7b1718af863caeff9afMarc Blank long originalTime = entityValues.getAsLong(Events.ORIGINAL_INSTANCE_TIME); 55982e51e06312c76f37900c7b1718af863caeff9afMarc Blank assertNotSame(0, originalTime); 56082e51e06312c76f37900c7b1718af863caeff9afMarc Blank // For an exception, RECURRENCE-ID is critical 5611c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank assertEquals(CalendarUtilities.millisToEasDateTime(originalTime, timeZone, 5621c48450c02ea33e498e17a1bfc9f95576d3027b6Marc Blank true /*withTime*/), vevent.get("RECURRENCE-ID" + ";TZID=" + timeZone.getID())); 56382e51e06312c76f37900c7b1718af863caeff9afMarc Blank } 56482e51e06312c76f37900c7b1718af863caeff9afMarc Blank 5654577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank public void testUtcOffsetString() { 5664577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertEquals(CalendarUtilities.utcOffsetString(540), "+0900"); 5674577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertEquals(CalendarUtilities.utcOffsetString(-480), "-0800"); 5684577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertEquals(CalendarUtilities.utcOffsetString(0), "+0000"); 5694577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank } 5706c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 5714577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank public void testFindTransitionDate() { 5724577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // We'll find some transitions and make sure that we're properly in or out of daylight time 5734577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // on either side of the transition. 5744577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Use CST for testing (any other will do as well, as long as it has DST) 5754577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank TimeZone tz = TimeZone.getTimeZone("US/Central"); 5764577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Get a calendar at January 1st of the current year 5774577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank GregorianCalendar calendar = new GregorianCalendar(tz); 5784577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank calendar.set(CalendarUtilities.sCurrentYear, Calendar.JANUARY, 1); 5794577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Get start and end times at start and end of year 5804577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank long startTime = calendar.getTimeInMillis(); 5814577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank long endTime = startTime + (365*CalendarUtilities.DAYS); 5824577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Find the first transition 5834577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank GregorianCalendar transitionCalendar = 5844577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank CalendarUtilities.findTransitionDate(tz, startTime, endTime, false); 5854577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank long transitionTime = transitionCalendar.getTimeInMillis(); 5864577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Before should be in standard time; after in daylight time 5874577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank Date beforeDate = new Date(transitionTime - CalendarUtilities.HOURS); 5884577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank Date afterDate = new Date(transitionTime + CalendarUtilities.HOURS); 5894577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertFalse(tz.inDaylightTime(beforeDate)); 5904577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertTrue(tz.inDaylightTime(afterDate)); 5914577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank 5924577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Find the next one... 5934577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank transitionCalendar = CalendarUtilities.findTransitionDate(tz, transitionTime + 5944577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank CalendarUtilities.DAYS, endTime, true); 5954577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank transitionTime = transitionCalendar.getTimeInMillis(); 5964577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // This time, Before should be in daylight time; after in standard time 5974577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank beforeDate = new Date(transitionTime - CalendarUtilities.HOURS); 5984577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank afterDate = new Date(transitionTime + CalendarUtilities.HOURS); 5994577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertTrue(tz.inDaylightTime(beforeDate)); 6004577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertFalse(tz.inDaylightTime(afterDate)); 6014577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank 6024577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Captain Renault: What in heaven's name brought you to Casablanca? 6034577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Rick: My health. I came to Casablanca for the waters. 6044577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Also, they have no daylight savings time 6054577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank tz = TimeZone.getTimeZone("Africa/Casablanca"); 6064577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Get a calendar at January 1st of the current year 6074577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank calendar = new GregorianCalendar(tz); 6084577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank calendar.set(CalendarUtilities.sCurrentYear, Calendar.JANUARY, 1); 6094577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Get start and end times at start and end of year 6104577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank startTime = calendar.getTimeInMillis(); 6114577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank endTime = startTime + (365*CalendarUtilities.DAYS); 6124577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Find the first transition 6134577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank transitionCalendar = CalendarUtilities.findTransitionDate(tz, startTime, endTime, false); 6144577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // There had better not be one 6154577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertNull(transitionCalendar); 6164577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank } 6176f3013b78708321879728c28db044ab233cb2016Marc Blank 6184577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank public void testRruleFromRecurrence() { 6194577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Every Monday for 2 weeks 6204577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank String rrule = CalendarUtilities.rruleFromRecurrence( 6214577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank 1 /*Weekly*/, 2 /*Occurrences*/, 1 /*Interval*/, 2 /*Monday*/, 0, 0, 0, null); 6224577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertEquals("FREQ=WEEKLY;INTERVAL=1;COUNT=2;BYDAY=MO", rrule); 6234577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Every Tuesday and Friday 6244577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank rrule = CalendarUtilities.rruleFromRecurrence( 6254577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank 1 /*Weekly*/, 0 /*Occurrences*/, 0 /*Interval*/, 36 /*Tue&Fri*/, 0, 0, 0, null); 6264577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertEquals("FREQ=WEEKLY;BYDAY=TU,FR", rrule); 6274577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // The last Saturday of the month 6284577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank rrule = CalendarUtilities.rruleFromRecurrence( 6294577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank 3 /*Monthly/DayofWeek*/, 0, 0, 64 /*Sat*/, 0, 5 /*Last*/, 0, null); 6304577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertEquals("FREQ=MONTHLY;BYDAY=-1SA", rrule); 6314577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // The third Wednesday and Thursday of the month 6324577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank rrule = CalendarUtilities.rruleFromRecurrence( 6334577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank 3 /*Monthly/DayofWeek*/, 0, 0, 24 /*Wed&Thu*/, 0, 3 /*3rd*/, 0, null); 6344577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertEquals("FREQ=MONTHLY;BYDAY=3WE,3TH", rrule); 6354577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // The 14th of the every month 6364577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank rrule = CalendarUtilities.rruleFromRecurrence( 6374577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank 2 /*Monthly/Date*/, 0, 0, 0, 14 /*14th*/, 0, 0, null); 6384577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertEquals("FREQ=MONTHLY;BYMONTHDAY=14", rrule); 6394577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // Every 31st of October 6404577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank rrule = CalendarUtilities.rruleFromRecurrence( 6414577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank 5 /*Yearly/Date*/, 0, 0, 0, 31 /*31st*/, 0, 10 /*October*/, null); 6424577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertEquals("FREQ=YEARLY;BYMONTHDAY=31;BYMONTH=10", rrule); 6434577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank // The first Tuesday of June 6444577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank rrule = CalendarUtilities.rruleFromRecurrence( 6454577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank 6 /*Yearly/Month/DayOfWeek*/, 0, 0, 4 /*Tue*/, 0, 1 /*1st*/, 6 /*June*/, null); 6464577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank assertEquals("FREQ=YEARLY;BYDAY=1TU;BYMONTH=6", rrule); 6474577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank } 6484577f71f76c94dc9fcb06efd2656970925dd3f6aMarc Blank 6496c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank /** 6506c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank * For debugging purposes, to help keep track of parsing errors. 6516c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank */ 6526c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank private class UnterminatedBlockException extends IOException { 6536c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank private static final long serialVersionUID = 1L; 6546c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank UnterminatedBlockException(String name) { 6556c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank super(name); 6566c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 6576c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 6586c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 6596c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank /** 6606c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank * A lightweight representation of block object containing a hash of individual values and an 6616c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank * array of inner blocks. The object is build by pulling elements from a BufferedReader. 6626c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank * NOTE: Multiple values of a given field are not supported. We'd see this with ATTENDEEs, for 6636c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank * example, and possibly RDATEs in VTIMEZONEs without an RRULE; these cases will be handled 6646c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank * at a later time. 6656c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank */ 6666c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank private class BlockHash { 6676c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank String name; 6686c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank HashMap<String, String> hash = new HashMap<String, String>(); 6696c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank ArrayList<BlockHash> blocks = new ArrayList<BlockHash>(); 6706c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 6716c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank BlockHash (String _name, BufferedReader reader) throws IOException { 6726c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank name = _name; 6736c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank String lastField = null; 6746c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank String lastValue = null; 6756c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank while (true) { 6766c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Get a line; we're done if it's null 6776c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank String line = reader.readLine(); 6786c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank if (line == null) { 6796c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank throw new UnterminatedBlockException(name); 6806c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 6816c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank int length = line.length(); 6826c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank if (length == 0) { 6836c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // We shouldn't ever see an empty line 6846c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank throw new IllegalArgumentException(); 6856c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 68688a94bca1922615564e70a27bb6ae72bca487c75Makoto Onuki // A line starting with tab is a continuation 68788a94bca1922615564e70a27bb6ae72bca487c75Makoto Onuki if (line.charAt(0) == '\t') { 6886c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Remember the line and length 6896c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank lastValue = line.substring(1); 6906c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Save the concatenation of old and new values 6916c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank hash.put(lastField, hash.get(lastField) + lastValue); 6926c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank continue; 6936c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 6946c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Find the field delimiter 6956c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank int pos = line.indexOf(':'); 6966c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // If not found, or at EOL, this is a bad ics 6976c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank if (pos < 0 || pos >= length) { 6986c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank throw new IllegalArgumentException(); 6996c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 7006c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Remember the field, value, and length 7016c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank lastField = line.substring(0, pos); 7026c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank lastValue = line.substring(pos + 1); 7036c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank if (lastField.equals("BEGIN")) { 7046c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank blocks.add(new BlockHash(lastValue, reader)); 7056c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank continue; 7066c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } else if (lastField.equals("END")) { 7076c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank if (!lastValue.equals(name)) { 7086c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank throw new UnterminatedBlockException(name); 7096c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 7106c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank break; 7116c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 7126c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 7136c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank // Save it away and continue 7146c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank hash.put(lastField, lastValue); 7156c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 7166c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 7176c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 7186c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank String get(String field) { 7196c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank return hash.get(field); 7206c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 7216c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 7226c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 72320225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki private BlockHash parseIcsContent(byte[] bytes) throws IOException { 724fe61f358ab67cac2aa454a6dd3ea6bbf876e343cMakoto Onuki BufferedReader reader = new BufferedReader(new StringReader(Utility.fromUtf8(bytes))); 7256c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank String line = reader.readLine(); 7266c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank if (!line.equals("BEGIN:VCALENDAR")) { 7276c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank throw new IllegalArgumentException(); 7286c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 7296c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank return new BlockHash("VCALENDAR", reader); 7306c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank } 7316c8b1ec088a1276ef5e18dd7137e18eb141dc5acMarc Blank 732bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank public void testBuildMessageTextFromEntityValues() { 733bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank // Set up a test event 734bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank String title = "Event Title"; 735bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title); 736bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank ContentValues entityValues = entity.getEntityValues(); 737bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank 738bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank // Save this away; we'll use it a few times below 739bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank Resources resources = mContext.getResources(); 740bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank Date date = new Date(entityValues.getAsLong(Events.DTSTART)); 741bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank String dateTimeString = DateFormat.getDateTimeInstance().format(date); 742bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank 743bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank // Get the text for this message 744bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank StringBuilder sb = new StringBuilder(); 745bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank CalendarUtilities.buildMessageTextFromEntityValues(mContext, entityValues, sb); 746bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank String text = sb.toString(); 747bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank // We'll just check the when and where 748bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank assertTrue(text.contains(resources.getString(R.string.meeting_when, dateTimeString))); 749bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank String location = entityValues.getAsString(Events.EVENT_LOCATION); 750bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank assertTrue(text.contains(resources.getString(R.string.meeting_where, location))); 751bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank 752bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank // Make this event recurring 753bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank entity.getEntityValues().put(Events.RRULE, "FREQ=WEEKLY;BYDAY=MO"); 754bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank sb = new StringBuilder(); 755bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank CalendarUtilities.buildMessageTextFromEntityValues(mContext, entityValues, sb); 756bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank text = sb.toString(); 757bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank assertTrue(text.contains(resources.getString(R.string.meeting_recurring, dateTimeString))); 758bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank } 759bf916efe955e07aba2a5bce9eecae325f84d4934Marc Blank 760aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank /** 761aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank * Sanity test for time zone generation. Most important, make sure that we can run through 762aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank * all of the time zones without generating an exception. Second, make sure that we're finding 763aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank * rules for at least 90% of time zones that use daylight time (empirically, it's more like 764aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank * 95%). Log those without rules. 765aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank * @throws IOException 766aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank */ 767aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank public void testTimeZoneToVTimezone() throws IOException { 768aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank SimpleIcsWriter writer = new SimpleIcsWriter(); 769aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank int rule = 0; 770aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank int nodst = 0; 771aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank int norule = 0; 772aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank ArrayList<String> norulelist = new ArrayList<String>(); 773aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank for (String tzs: TimeZone.getAvailableIDs()) { 774aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank TimeZone tz = TimeZone.getTimeZone(tzs); 775aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank writer = new SimpleIcsWriter(); 776aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank CalendarUtilities.timeZoneToVTimezone(tz, writer); 777aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank String vc = writer.toString(); 778aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank boolean hasRule = vc.indexOf("RRULE") > 0; 779aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank if (hasRule) { 780aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank rule++; 781aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank } else if (tz.useDaylightTime()) { 782aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank norule++; 783aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank norulelist.add(tz.getID()); 784aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank } else { 785aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank nodst++; 786aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank } 787aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank } 788aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank assertTrue(norule < rule/10); 789aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank Log.d("TimeZoneGeneration", 790aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank "Rule: " + rule + ", No DST: " + nodst + ", No rule: " + norule); 791aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank for (String nr: norulelist) { 792aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank Log.d("TimeZoneGeneration", "No rule: " + nr); 793aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank } 794aec526f141f49658fdc5535c76bdf8c879ae95b9Marc Blank } 7957e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank 7967e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank public void testGetUidFromGlobalObjId() { 7977e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank // This is a "foreign" uid (from some vCalendar client) 7987e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank String globalObjId = "BAAAAIIA4AB0xbcQGoLgCAAAAAAAAAAAAAAAAAAAAAAAAAAAMQAAA" + 7997e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank "HZDYWwtVWlkAQAAADI3NjU1NmRkLTg1MzAtNGZiZS1iMzE0LThiM2JlYTYwMjE0OQA="; 8007e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank String uid = CalendarUtilities.getUidFromGlobalObjId(globalObjId); 8017e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank assertEquals(uid, "276556dd-8530-4fbe-b314-8b3bea602149"); 8027e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank // This is a native EAS uid 8037e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank globalObjId = 8047e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank "BAAAAIIA4AB0xbcQGoLgCAAAAADACTu7KbPKAQAAAAAAAAAAEAAAAObgsG6HVt1Fmy+7GlLbGhY="; 8057e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank uid = CalendarUtilities.getUidFromGlobalObjId(globalObjId); 8067e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank assertEquals(uid, "040000008200E00074C5B7101A82E00800000000C0093BBB29B3CA" + 8077e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank "01000000000000000010000000E6E0B06E8756DD459B2FBB1A52DB1A16"); 8087e30b2e22f597b3e4b902c333a8dafc8a21e8b86Marc Blank } 809095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank 810095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank public void testSelfAttendeeStatusFromBusyStatus() { 811095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank assertEquals(Attendees.ATTENDEE_STATUS_ACCEPTED, 8128a19af3739aad25d26754e8a52e986cc38b41db6Marc Blank CalendarUtilities.attendeeStatusFromBusyStatus( 813095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank CalendarUtilities.BUSY_STATUS_BUSY)); 814095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank assertEquals(Attendees.ATTENDEE_STATUS_TENTATIVE, 8158a19af3739aad25d26754e8a52e986cc38b41db6Marc Blank CalendarUtilities.attendeeStatusFromBusyStatus( 816095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank CalendarUtilities.BUSY_STATUS_TENTATIVE)); 817095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank assertEquals(Attendees.ATTENDEE_STATUS_NONE, 8188a19af3739aad25d26754e8a52e986cc38b41db6Marc Blank CalendarUtilities.attendeeStatusFromBusyStatus( 819095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank CalendarUtilities.BUSY_STATUS_FREE)); 820095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank assertEquals(Attendees.ATTENDEE_STATUS_NONE, 8218a19af3739aad25d26754e8a52e986cc38b41db6Marc Blank CalendarUtilities.attendeeStatusFromBusyStatus( 8221880ad6a83120b89ed239858d27d3e63242160e6Marc Blank CalendarUtilities.BUSY_STATUS_OUT_OF_OFFICE)); 823095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank } 824095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank 825095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank public void testBusyStatusFromSelfStatus() { 826095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank assertEquals(CalendarUtilities.BUSY_STATUS_FREE, 8278a19af3739aad25d26754e8a52e986cc38b41db6Marc Blank CalendarUtilities.busyStatusFromAttendeeStatus( 828095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank Attendees.ATTENDEE_STATUS_DECLINED)); 8291880ad6a83120b89ed239858d27d3e63242160e6Marc Blank assertEquals(CalendarUtilities.BUSY_STATUS_FREE, 8308a19af3739aad25d26754e8a52e986cc38b41db6Marc Blank CalendarUtilities.busyStatusFromAttendeeStatus( 831095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank Attendees.ATTENDEE_STATUS_NONE)); 8321880ad6a83120b89ed239858d27d3e63242160e6Marc Blank assertEquals(CalendarUtilities.BUSY_STATUS_FREE, 8338a19af3739aad25d26754e8a52e986cc38b41db6Marc Blank CalendarUtilities.busyStatusFromAttendeeStatus( 834095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank Attendees.ATTENDEE_STATUS_INVITED)); 835095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank assertEquals(CalendarUtilities.BUSY_STATUS_TENTATIVE, 8368a19af3739aad25d26754e8a52e986cc38b41db6Marc Blank CalendarUtilities.busyStatusFromAttendeeStatus( 837095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank Attendees.ATTENDEE_STATUS_TENTATIVE)); 838095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank assertEquals(CalendarUtilities.BUSY_STATUS_BUSY, 8398a19af3739aad25d26754e8a52e986cc38b41db6Marc Blank CalendarUtilities.busyStatusFromAttendeeStatus( 840095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank Attendees.ATTENDEE_STATUS_ACCEPTED)); 841095eee41565900a2509256ffcbf6cd67a4c4e345Marc Blank } 8423e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank 8433e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank public void testGetUtcAllDayCalendarTime() { 8443e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank GregorianCalendar correctUtc = new GregorianCalendar(TimeZone.getTimeZone("UTC")); 8453e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank correctUtc.set(2011, 2, 10, 0, 0, 0); 8463e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank long correctUtcTime = correctUtc.getTimeInMillis(); 8473e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank 8483e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank TimeZone localTimeZone = TimeZone.getTimeZone("GMT-0700"); 8493e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank GregorianCalendar localCalendar = new GregorianCalendar(localTimeZone); 8503e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank localCalendar.set(2011, 2, 10, 12, 23, 34); 8513e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank long localTimeMillis = localCalendar.getTimeInMillis(); 8523e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank long convertedUtcTime = 8533e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank CalendarUtilities.getUtcAllDayCalendarTime(localTimeMillis, localTimeZone); 8543e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank // Milliseconds aren't zeroed out and may not be the same 8553e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank assertEquals(convertedUtcTime/1000, correctUtcTime/1000); 8563e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank 8573e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank localTimeZone = TimeZone.getTimeZone("GMT+0700"); 8583e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank localCalendar = new GregorianCalendar(localTimeZone); 8593e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank localCalendar.set(2011, 2, 10, 12, 23, 34); 8603e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank localTimeMillis = localCalendar.getTimeInMillis(); 8613e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank convertedUtcTime = 8623e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank CalendarUtilities.getUtcAllDayCalendarTime(localTimeMillis, localTimeZone); 8633e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank assertEquals(convertedUtcTime/1000, correctUtcTime/1000); 8643e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank } 8653e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank 8663e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank public void testGetLocalAllDayCalendarTime() { 8673e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank TimeZone utcTimeZone = TimeZone.getTimeZone("UTC"); 8683e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank TimeZone localTimeZone = TimeZone.getTimeZone("GMT-0700"); 8693e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank GregorianCalendar correctLocal = new GregorianCalendar(localTimeZone); 8703e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank correctLocal.set(2011, 2, 10, 0, 0, 0); 8713e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank long correctLocalTime = correctLocal.getTimeInMillis(); 8723e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank 8733e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank GregorianCalendar utcCalendar = new GregorianCalendar(utcTimeZone); 8743e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank utcCalendar.set(2011, 2, 10, 12, 23, 34); 8753e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank long utcTimeMillis = utcCalendar.getTimeInMillis(); 8763e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank long convertedLocalTime = 8773e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank CalendarUtilities.getLocalAllDayCalendarTime(utcTimeMillis, localTimeZone); 8783e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank // Milliseconds aren't zeroed out and may not be the same 8793e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank assertEquals(convertedLocalTime/1000, correctLocalTime/1000); 8803e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank 8813e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank localTimeZone = TimeZone.getTimeZone("GMT+0700"); 8823e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank correctLocal = new GregorianCalendar(localTimeZone); 8833e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank correctLocal.set(2011, 2, 10, 0, 0, 0); 8843e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank correctLocalTime = correctLocal.getTimeInMillis(); 8853e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank 8863e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank utcCalendar = new GregorianCalendar(utcTimeZone); 8873e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank utcCalendar.set(2011, 2, 10, 12, 23, 34); 8883e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank utcTimeMillis = utcCalendar.getTimeInMillis(); 8893e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank convertedLocalTime = 8903e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank CalendarUtilities.getLocalAllDayCalendarTime(utcTimeMillis, localTimeZone); 8913e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank // Milliseconds aren't zeroed out and may not be the same 8923e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank assertEquals(convertedLocalTime/1000, correctLocalTime/1000); 8933e065170f3374ecb78af2e68bcb28040b83fd928Marc Blank } 894efcde27bf74acdd82bb0aad0ad1fd0b767ca5f18Andy Stadler 895efcde27bf74acdd82bb0aad0ad1fd0b767ca5f18Andy Stadler public void testGetIntegerValueAsBoolean() { 896efcde27bf74acdd82bb0aad0ad1fd0b767ca5f18Andy Stadler ContentValues cv = new ContentValues(); 897efcde27bf74acdd82bb0aad0ad1fd0b767ca5f18Andy Stadler cv.put("A", 1); 898efcde27bf74acdd82bb0aad0ad1fd0b767ca5f18Andy Stadler cv.put("B", 69); 899efcde27bf74acdd82bb0aad0ad1fd0b767ca5f18Andy Stadler cv.put("C", 0); 900efcde27bf74acdd82bb0aad0ad1fd0b767ca5f18Andy Stadler assertTrue(CalendarUtilities.getIntegerValueAsBoolean(cv, "A")); 901efcde27bf74acdd82bb0aad0ad1fd0b767ca5f18Andy Stadler assertTrue(CalendarUtilities.getIntegerValueAsBoolean(cv, "B")); 902efcde27bf74acdd82bb0aad0ad1fd0b767ca5f18Andy Stadler assertFalse(CalendarUtilities.getIntegerValueAsBoolean(cv, "C")); 903efcde27bf74acdd82bb0aad0ad1fd0b767ca5f18Andy Stadler assertFalse(CalendarUtilities.getIntegerValueAsBoolean(cv, "D")); 904efcde27bf74acdd82bb0aad0ad1fd0b767ca5f18Andy Stadler } 905f3fcb8929e3690bc092aec0d4d643b346f079acdMarc Blank} 906802a7d69b54b3d560ea12255d44503dda54f1dbdMarc Blank 907802a7d69b54b3d560ea12255d44503dda54f1dbdMarc Blank // TODO Planned unit tests 908802a7d69b54b3d560ea12255d44503dda54f1dbdMarc Blank // findNextTransition 909802a7d69b54b3d560ea12255d44503dda54f1dbdMarc Blank // recurrenceFromRrule 910802a7d69b54b3d560ea12255d44503dda54f1dbdMarc Blank // timeZoneToTziStringImpl 911802a7d69b54b3d560ea12255d44503dda54f1dbdMarc Blank // getDSTCalendars 912802a7d69b54b3d560ea12255d44503dda54f1dbdMarc Blank // millisToVCalendarTime 913802a7d69b54b3d560ea12255d44503dda54f1dbdMarc Blank // millisToEasDateTime 914802a7d69b54b3d560ea12255d44503dda54f1dbdMarc Blank // getTrueTransitionMinute 915802a7d69b54b3d560ea12255d44503dda54f1dbdMarc Blank // getTrueTransitionHour 916802a7d69b54b3d560ea12255d44503dda54f1dbdMarc Blank 917