15862a85e17e81866ca82a9905577931947fbd44eMarc Blank/* 25862a85e17e81866ca82a9905577931947fbd44eMarc Blank * Copyright (C) 2010 The Android Open Source Project 35862a85e17e81866ca82a9905577931947fbd44eMarc Blank * 45862a85e17e81866ca82a9905577931947fbd44eMarc Blank * Licensed under the Apache License, Version 2.0 (the "License"); 55862a85e17e81866ca82a9905577931947fbd44eMarc Blank * you may not use this file except in compliance with the License. 65862a85e17e81866ca82a9905577931947fbd44eMarc Blank * You may obtain a copy of the License at 75862a85e17e81866ca82a9905577931947fbd44eMarc Blank * 85862a85e17e81866ca82a9905577931947fbd44eMarc Blank * http://www.apache.org/licenses/LICENSE-2.0 95862a85e17e81866ca82a9905577931947fbd44eMarc Blank * 105862a85e17e81866ca82a9905577931947fbd44eMarc Blank * Unless required by applicable law or agreed to in writing, software 115862a85e17e81866ca82a9905577931947fbd44eMarc Blank * distributed under the License is distributed on an "AS IS" BASIS, 125862a85e17e81866ca82a9905577931947fbd44eMarc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135862a85e17e81866ca82a9905577931947fbd44eMarc Blank * See the License for the specific language governing permissions and 145862a85e17e81866ca82a9905577931947fbd44eMarc Blank * limitations under the License. 155862a85e17e81866ca82a9905577931947fbd44eMarc Blank */ 165862a85e17e81866ca82a9905577931947fbd44eMarc Blank 175862a85e17e81866ca82a9905577931947fbd44eMarc Blankpackage com.android.exchange.utility; 185862a85e17e81866ca82a9905577931947fbd44eMarc Blank 193f8e329b8d638d02e0b48ad504b18690cefc68e9Marc Blankimport android.content.ContentValues; 203f8e329b8d638d02e0b48ad504b18690cefc68e9Marc Blankimport android.content.Entity; 213f8e329b8d638d02e0b48ad504b18690cefc68e9Marc Blankimport android.content.res.Resources; 223f8e329b8d638d02e0b48ad504b18690cefc68e9Marc Blankimport android.provider.CalendarContract.Attendees; 233f8e329b8d638d02e0b48ad504b18690cefc68e9Marc Blankimport android.provider.CalendarContract.Events; 243f8e329b8d638d02e0b48ad504b18690cefc68e9Marc Blankimport android.test.suitebuilder.annotation.MediumTest; 253f8e329b8d638d02e0b48ad504b18690cefc68e9Marc Blankimport android.util.Log; 263f8e329b8d638d02e0b48ad504b18690cefc68e9Marc Blank 27c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.mail.Address; 287372782488977df778a33d990401ce9e397f646bMarc Blankimport com.android.emailcommon.provider.Account; 29c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.provider.EmailContent.Attachment; 30c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.provider.EmailContent.Message; 31c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.utility.Utility; 32c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.exchange.R; 33f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blankimport com.android.exchange.adapter.CalendarSyncAdapter; 34c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.exchange.adapter.CalendarSyncAdapter.EasCalendarSyncParser; 35f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blankimport com.android.exchange.adapter.Parser; 36f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blankimport com.android.exchange.adapter.Serializer; 37f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blankimport com.android.exchange.adapter.SyncAdapterTestCase; 38f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blankimport com.android.exchange.adapter.Tags; 395c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 401c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blankimport java.io.BufferedReader; 41f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blankimport java.io.ByteArrayInputStream; 421c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blankimport java.io.IOException; 431c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blankimport java.io.StringReader; 449ca8918b82221dd441293973ffb84d565a52993aMarc Blankimport java.text.DateFormat; 451c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blankimport java.util.ArrayList; 46c10a3beef4f048292e6a4ceb31527c5123801517Marc Blankimport java.util.Calendar; 47820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blankimport java.util.Date; 48c10a3beef4f048292e6a4ceb31527c5123801517Marc Blankimport java.util.GregorianCalendar; 491c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blankimport java.util.HashMap; 505862a85e17e81866ca82a9905577931947fbd44eMarc Blankimport java.util.TimeZone; 515862a85e17e81866ca82a9905577931947fbd44eMarc Blank 52377230593dca7cb01483bfaf93959e5821f5f028Marc Blank/** 53377230593dca7cb01483bfaf93959e5821f5f028Marc Blank * Tests of EAS Calendar Utilities 54377230593dca7cb01483bfaf93959e5821f5f028Marc Blank * You can run this entire test case with: 55c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blank * runtest -c com.android.exchange.utility.CalendarUtilitiesTests exchange 56377230593dca7cb01483bfaf93959e5821f5f028Marc Blank * 57377230593dca7cb01483bfaf93959e5821f5f028Marc Blank * Please see RFC2445 for RRULE definition 58377230593dca7cb01483bfaf93959e5821f5f028Marc Blank * http://www.ietf.org/rfc/rfc2445.txt 59377230593dca7cb01483bfaf93959e5821f5f028Marc Blank */ 60604a1cf6f2401d78f57edcfb702d560d9c80dd14Marc Blank@MediumTest 61f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blankpublic class CalendarUtilitiesTests extends SyncAdapterTestCase<CalendarSyncAdapter> { 625862a85e17e81866ca82a9905577931947fbd44eMarc Blank 635862a85e17e81866ca82a9905577931947fbd44eMarc Blank // Some prebuilt time zones, Base64 encoded (as they arrive from EAS) 64377230593dca7cb01483bfaf93959e5821f5f028Marc Blank // More time zones to be added over time 65377230593dca7cb01483bfaf93959e5821f5f028Marc Blank 66377230593dca7cb01483bfaf93959e5821f5f028Marc Blank // Not all time zones are appropriate for testing. For example, ISRAEL_STANDARD_TIME cannot be 67377230593dca7cb01483bfaf93959e5821f5f028Marc Blank // used because DST is determined from year to year in a non-standard way (related to the lunar 68377230593dca7cb01483bfaf93959e5821f5f028Marc Blank // calendar); therefore, the test would only work during the year in which it was created 6979268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank 7079268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank // This time zone has no DST 7179268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank private static final String ASIA_CALCUTTA_TIME = 725862a85e17e81866ca82a9905577931947fbd44eMarc Blank "tv7//0kAbgBkAGkAYQAgAFMAdABhAG4AZABhAHIAZAAgAFQAaQBtAGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + 735862a85e17e81866ca82a9905577931947fbd44eMarc Blank "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEkAbgBkAGkAYQAgAEQAYQB5AGwAaQBnAGgAdAAgAFQAaQBtAGUA" + 745862a85e17e81866ca82a9905577931947fbd44eMarc Blank "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; 7579268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank 7679268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank // This time zone is equivalent to PST and uses DST 7779268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank private static final String AMERICA_DAWSON_TIME = 785862a85e17e81866ca82a9905577931947fbd44eMarc Blank "4AEAAFAAYQBjAGkAZgBpAGMAIABTAHQAYQBuAGQAYQByAGQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAA" + 795862a85e17e81866ca82a9905577931947fbd44eMarc Blank "AAAAAAAAAAsAAAABAAIAAAAAAAAAAAAAAFAAYQBjAGkAZgBpAGMAIABEAGEAeQBsAGkAZwBoAHQAIABUAGkA" + 805862a85e17e81866ca82a9905577931947fbd44eMarc Blank "bQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAAAAAAAAAxP///w=="; 815862a85e17e81866ca82a9905577931947fbd44eMarc Blank 8279268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank // Test a southern hemisphere time zone w/ DST 8379268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank private static final String AUSTRALIA_ACT_TIME = 8479268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank "qP3//0EAVQBTACAARQBhAHMAdABlAHIAbgAgAFMAdABhAG4AZABhAHIAZAAgAFQAaQBtAGUAAAAAAAAAAAAA" + 8579268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank "AAAAAAAAAAQAAAABAAMAAAAAAAAAAAAAAEEAVQBTACAARQBhAHMAdABlAHIAbgAgAEQAYQB5AGwAaQBnAGgA" + 8679268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank "dAAgAFQAaQBtAGUAAAAAAAAAAAAAAAAAAAAAAAoAAAABAAIAAAAAAAAAxP///w=="; 8779268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank 88270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank // Test a timezone with GMT bias but bogus DST parameters (there is no equivalent time zone 89270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank // in the database) 90270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank private static final String GMT_UNKNOWN_DAYLIGHT_TIME = 91270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank "AAAAACgARwBNAFQAKwAwADAAOgAwADAAKQAgAFQAaQBtAGUAIABaAG8AbgBlAAAAAAAAAAAAAAAAAAAAAAAA" + 92270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank "AAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAACgARwBNAFQAKwAwADAAOgAwADAAKQAgAFQAaQBtAGUAIABaAG8A" + 93270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank "bgBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAFAAEAAAAAAAAAxP///w=="; 94270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank 955bb2c4930c27c5385ff1baf033d1f1a97d770d14Marc Blank // This time zone has no DST, but earlier, buggy code retrieved a TZ WITH DST 965bb2c4930c27c5385ff1baf033d1f1a97d770d14Marc Blank private static final String ARIZONA_TIME = 975bb2c4930c27c5385ff1baf033d1f1a97d770d14Marc Blank "pAEAAFUAUwAgAE0AbwB1AG4AdABhAGkAbgAgAFMAdABhAG4AZABhAHIAZAAgAFQAaQBtAGUAAAAAAAAAAAAA" + 985bb2c4930c27c5385ff1baf033d1f1a97d770d14Marc Blank "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFUAUwAgAE0AbwB1AG4AdABhAGkAbgAgAEQAYQB5AGwAaQBnAGgA" + 995bb2c4930c27c5385ff1baf033d1f1a97d770d14Marc Blank "dAAgAFQAaQBtAGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; 1005bb2c4930c27c5385ff1baf033d1f1a97d770d14Marc Blank 1014868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank private static final String HAWAII_TIME = 1024868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank "WAIAAEgAYQB3AGEAaQBpAGEAbgAgAFMAdABhAG4AZABhAHIAZAAgAFQAaQBtAGUAAAAAAAAAAAAAAAAAAAAA" + 1034868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAYQB3AGEAaQBpAGEAbgAgAEQAYQB5AGwAaQBnAGgAdAAgAFQA" + 1044868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank "aQBtAGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; 1054868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank 1062c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank // This is time zone sent by Exchange 2007, apparently; the start time of DST for the eastern 1072c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank // time zone (EST) is off by two hours, which we should correct in our new "lenient" code 1082c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank private static final String LENIENT_EASTERN_TIME = 1092c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank "LAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + 1102c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank "AAAAAAAAAAsAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + 1112c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAAAAAAAAAAAxP///w=="; 1122c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank 1139ca8918b82221dd441293973ffb84d565a52993aMarc Blank private static final String ORGANIZER = "organizer@server.com"; 1149ca8918b82221dd441293973ffb84d565a52993aMarc Blank private static final String ATTENDEE = "attendee@server.com"; 1159ca8918b82221dd441293973ffb84d565a52993aMarc Blank 1165862a85e17e81866ca82a9905577931947fbd44eMarc Blank public void testGetSet() { 1175862a85e17e81866ca82a9905577931947fbd44eMarc Blank byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7}; 1185862a85e17e81866ca82a9905577931947fbd44eMarc Blank 1195862a85e17e81866ca82a9905577931947fbd44eMarc Blank // First, check that getWord/Long are properly little endian 1205862a85e17e81866ca82a9905577931947fbd44eMarc Blank assertEquals(0x0100, CalendarUtilities.getWord(bytes, 0)); 1215862a85e17e81866ca82a9905577931947fbd44eMarc Blank assertEquals(0x03020100, CalendarUtilities.getLong(bytes, 0)); 1225862a85e17e81866ca82a9905577931947fbd44eMarc Blank assertEquals(0x07060504, CalendarUtilities.getLong(bytes, 4)); 1235862a85e17e81866ca82a9905577931947fbd44eMarc Blank 1245862a85e17e81866ca82a9905577931947fbd44eMarc Blank // Set some words and longs 1255862a85e17e81866ca82a9905577931947fbd44eMarc Blank CalendarUtilities.setWord(bytes, 0, 0xDEAD); 1265862a85e17e81866ca82a9905577931947fbd44eMarc Blank CalendarUtilities.setLong(bytes, 2, 0xBEEFBEEF); 1275862a85e17e81866ca82a9905577931947fbd44eMarc Blank CalendarUtilities.setWord(bytes, 6, 0xCEDE); 1285862a85e17e81866ca82a9905577931947fbd44eMarc Blank 1295862a85e17e81866ca82a9905577931947fbd44eMarc Blank // Retrieve them 1305862a85e17e81866ca82a9905577931947fbd44eMarc Blank assertEquals(0xDEAD, CalendarUtilities.getWord(bytes, 0)); 1315862a85e17e81866ca82a9905577931947fbd44eMarc Blank assertEquals(0xBEEFBEEF, CalendarUtilities.getLong(bytes, 2)); 1325862a85e17e81866ca82a9905577931947fbd44eMarc Blank assertEquals(0xCEDE, CalendarUtilities.getWord(bytes, 6)); 1335862a85e17e81866ca82a9905577931947fbd44eMarc Blank } 1345862a85e17e81866ca82a9905577931947fbd44eMarc Blank 1355862a85e17e81866ca82a9905577931947fbd44eMarc Blank public void testParseTimeZoneEndToEnd() { 13679268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank TimeZone tz = CalendarUtilities.tziStringToTimeZone(AMERICA_DAWSON_TIME); 13779268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank assertEquals("America/Dawson", tz.getID()); 13879268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank tz = CalendarUtilities.tziStringToTimeZone(ASIA_CALCUTTA_TIME); 13979268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank assertEquals("Asia/Calcutta", tz.getID()); 14079268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank tz = CalendarUtilities.tziStringToTimeZone(AUSTRALIA_ACT_TIME); 14179268e63dbda6ebc94d20e72e2bb1c245ee64678Marc Blank assertEquals("Australia/ACT", tz.getID()); 1422c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank 1432c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank // Test peculiar MS sent EST data with and without lenient precision; send standard 1442c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank // precision + 1 (i.e. 1ms) to make sure the code doesn't automatically flip to lenient 1452c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank // when the tz isn't found 1462c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank tz = CalendarUtilities.tziStringToTimeZoneImpl(LENIENT_EASTERN_TIME, 1472c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank CalendarUtilities.STANDARD_DST_PRECISION+1); 1482c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank assertEquals("America/Atikokan", tz.getID()); 1492c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank tz = CalendarUtilities.tziStringToTimeZoneImpl(LENIENT_EASTERN_TIME, 1502c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank CalendarUtilities.LENIENT_DST_PRECISION); 1512c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank assertEquals("America/Detroit", tz.getID()); 1522c7d44b182654120a98921cbc864be2d135c8fdaMarc Blank 153270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank tz = CalendarUtilities.tziStringToTimeZone(GMT_UNKNOWN_DAYLIGHT_TIME); 154270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank int bias = tz.getOffset(System.currentTimeMillis()); 155270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank assertEquals(0, bias); 1564868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank // Make sure non-DST TZ's work properly when the tested zone is the default zone 1574868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank TimeZone.setDefault(TimeZone.getTimeZone("America/Phoenix")); 1585bb2c4930c27c5385ff1baf033d1f1a97d770d14Marc Blank tz = CalendarUtilities.tziStringToTimeZone(ARIZONA_TIME); 1595bb2c4930c27c5385ff1baf033d1f1a97d770d14Marc Blank assertEquals("America/Phoenix", tz.getID()); 1604868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank TimeZone.setDefault(TimeZone.getTimeZone("Pacific/Honolulu")); 1614868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank tz = CalendarUtilities.tziStringToTimeZone(HAWAII_TIME); 1624868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank assertEquals("Pacific/Honolulu", tz.getID()); 1634868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank // Make sure non-DST TZ's get the proper offset and DST status otherwise 1644868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank CalendarUtilities.clearTimeZoneCache(); 1654868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank TimeZone azTime = TimeZone.getTimeZone("America/Phoenix"); 1664868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); 1674868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank tz = CalendarUtilities.tziStringToTimeZone(ARIZONA_TIME); 1684868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank assertFalse("America/Phoenix".equals(tz.getID())); 1694868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank assertFalse(tz.useDaylightTime()); 1704868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank // It doesn't matter what time is passed in, since neither TZ has dst 1714868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank long now = System.currentTimeMillis(); 1724868e0f09b58104741a5593f6097589ac62c6ce3Marc Blank assertEquals(azTime.getOffset(now), tz.getOffset(now)); 1735862a85e17e81866ca82a9905577931947fbd44eMarc Blank } 1745862a85e17e81866ca82a9905577931947fbd44eMarc Blank 175f35b67cef20189c12a1a387dedf200eb30089725Marc Blank public void testGenerateEasDayOfWeek() { 176b129a5f1b340ae6362397685c407099ceae8d9e9Marc Blank String byDay = "TU,WE,SA"; 177377230593dca7cb01483bfaf93959e5821f5f028Marc Blank // TU = 4, WE = 8; SA = 64; 178f35b67cef20189c12a1a387dedf200eb30089725Marc Blank assertEquals("76", CalendarUtilities.generateEasDayOfWeek(byDay)); 179377230593dca7cb01483bfaf93959e5821f5f028Marc Blank // MO = 2, TU = 4; WE = 8; TH = 16; FR = 32 180b129a5f1b340ae6362397685c407099ceae8d9e9Marc Blank byDay = "MO,TU,WE,TH,FR"; 181f35b67cef20189c12a1a387dedf200eb30089725Marc Blank assertEquals("62", CalendarUtilities.generateEasDayOfWeek(byDay)); 182377230593dca7cb01483bfaf93959e5821f5f028Marc Blank // SU = 1 183f35b67cef20189c12a1a387dedf200eb30089725Marc Blank byDay = "SU"; 184f35b67cef20189c12a1a387dedf200eb30089725Marc Blank assertEquals("1", CalendarUtilities.generateEasDayOfWeek(byDay)); 185f35b67cef20189c12a1a387dedf200eb30089725Marc Blank } 186f35b67cef20189c12a1a387dedf200eb30089725Marc Blank 187f35b67cef20189c12a1a387dedf200eb30089725Marc Blank public void testTokenFromRrule() { 188f35b67cef20189c12a1a387dedf200eb30089725Marc Blank String rrule = "FREQ=DAILY;INTERVAL=1;BYDAY=WE,TH,SA;BYMONTHDAY=17"; 189f35b67cef20189c12a1a387dedf200eb30089725Marc Blank assertEquals("DAILY", CalendarUtilities.tokenFromRrule(rrule, "FREQ=")); 190f35b67cef20189c12a1a387dedf200eb30089725Marc Blank assertEquals("1", CalendarUtilities.tokenFromRrule(rrule, "INTERVAL=")); 191f35b67cef20189c12a1a387dedf200eb30089725Marc Blank assertEquals("17", CalendarUtilities.tokenFromRrule(rrule, "BYMONTHDAY=")); 192b129a5f1b340ae6362397685c407099ceae8d9e9Marc Blank assertEquals("WE,TH,SA", CalendarUtilities.tokenFromRrule(rrule, "BYDAY=")); 193f35b67cef20189c12a1a387dedf200eb30089725Marc Blank assertNull(CalendarUtilities.tokenFromRrule(rrule, "UNTIL=")); 194f35b67cef20189c12a1a387dedf200eb30089725Marc Blank } 195f35b67cef20189c12a1a387dedf200eb30089725Marc Blank 19621c3c670ff6b932a4ecbeda230bb160178bdd957Marc Blank public void testRecurrenceUntilToEasUntil() { 19760df2ad267f1ad7aed45b583adcd1a5bb2a006b0Marc Blank TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); 19860df2ad267f1ad7aed45b583adcd1a5bb2a006b0Marc Blank // Case where local time crosses into next day in GMT 19960df2ad267f1ad7aed45b583adcd1a5bb2a006b0Marc Blank assertEquals("20110730T000000Z", 20060df2ad267f1ad7aed45b583adcd1a5bb2a006b0Marc Blank CalendarUtilities.recurrenceUntilToEasUntil("20110731T025959Z")); 20160df2ad267f1ad7aed45b583adcd1a5bb2a006b0Marc Blank // Case where local time does not cross into next day in GMT 20260df2ad267f1ad7aed45b583adcd1a5bb2a006b0Marc Blank assertEquals("20110730T000000Z", 20360df2ad267f1ad7aed45b583adcd1a5bb2a006b0Marc Blank CalendarUtilities.recurrenceUntilToEasUntil("20110730T235959Z")); 20421c3c670ff6b932a4ecbeda230bb160178bdd957Marc Blank } 20521c3c670ff6b932a4ecbeda230bb160178bdd957Marc Blank 206c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank public void testParseEmailDateTimeToMillis(String date) { 207c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank // Format for email date strings is 2010-02-23T16:00:00.000Z 208c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank String dateString = "2010-02-23T15:16:17.000Z"; 2098e26c42accbaf72eff6694173496aba0e6aa37f6Mihai Preda long dateTime = Utility.parseEmailDateTimeToMillis(dateString); 210c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank GregorianCalendar cal = new GregorianCalendar(); 211c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank cal.setTimeInMillis(dateTime); 212c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank cal.setTimeZone(TimeZone.getTimeZone("GMT")); 213c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.YEAR), 2010); 214c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.MONTH), 1); // 0 based 215c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.DAY_OF_MONTH), 23); 216c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.HOUR_OF_DAY), 16); 217c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.MINUTE), 16); 218c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.SECOND), 17); 219c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank } 220c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank 221c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank public void testParseDateTimeToMillis(String date) { 222c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank // Format for calendar date strings is 20100223T160000000Z 223c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank String dateString = "20100223T151617000Z"; 2248e26c42accbaf72eff6694173496aba0e6aa37f6Mihai Preda long dateTime = Utility.parseDateTimeToMillis(dateString); 225c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank GregorianCalendar cal = new GregorianCalendar(); 226c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank cal.setTimeInMillis(dateTime); 227c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank cal.setTimeZone(TimeZone.getTimeZone("GMT")); 228c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.YEAR), 2010); 229c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.MONTH), 1); // 0 based 230c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.DAY_OF_MONTH), 23); 231c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.HOUR_OF_DAY), 16); 232c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.MINUTE), 16); 233c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank assertEquals(cal.get(Calendar.SECOND), 17); 234c10a3beef4f048292e6a4ceb31527c5123801517Marc Blank } 23521c3c670ff6b932a4ecbeda230bb160178bdd957Marc Blank 2361c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank private Entity setupTestEventEntity(String organizer, String attendee, String title) { 2375c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank // Create an Entity for an Event 2385c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank ContentValues entityValues = new ContentValues(); 2395c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank Entity entity = new Entity(entityValues); 2405c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 2415c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank // Set up values for the Event 2425c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank String location = "Meeting Location"; 2435c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 2445c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank // Fill in times, location, title, and organizer 2455c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank entityValues.put("DTSTAMP", 2465c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank CalendarUtilities.convertEmailDateTimeToCalendarDateTime("2010-04-05T14:30:51Z")); 2475c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank entityValues.put(Events.DTSTART, 2488e26c42accbaf72eff6694173496aba0e6aa37f6Mihai Preda Utility.parseEmailDateTimeToMillis("2010-04-12T18:30:00Z")); 2495c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank entityValues.put(Events.DTEND, 2508e26c42accbaf72eff6694173496aba0e6aa37f6Mihai Preda Utility.parseEmailDateTimeToMillis("2010-04-12T19:30:00Z")); 2515c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank entityValues.put(Events.EVENT_LOCATION, location); 2525c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank entityValues.put(Events.TITLE, title); 2535c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank entityValues.put(Events.ORGANIZER, organizer); 25404c880a6b5ad041f172d4b1eeecc06d6a06e4141RoboErik entityValues.put(Events.SYNC_DATA2, "31415926535"); 2555c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 2565c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank // Add the attendee 2575c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank ContentValues attendeeValues = new ContentValues(); 2585c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank attendeeValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE); 2595c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank attendeeValues.put(Attendees.ATTENDEE_EMAIL, attendee); 2605c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank entity.addSubValue(Attendees.CONTENT_URI, attendeeValues); 2615c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 2625c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank // Add the organizer 2635c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank ContentValues organizerValues = new ContentValues(); 2645c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank organizerValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ORGANIZER); 2655c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank organizerValues.put(Attendees.ATTENDEE_EMAIL, organizer); 2665c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank entity.addSubValue(Attendees.CONTENT_URI, organizerValues); 2671c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank return entity; 2681c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 2695c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 270dafc866120dac68fabbddcc9943e3995894c5244Marc Blank private Entity setupTestExceptionEntity(String organizer, String attendee, String title) { 271dafc866120dac68fabbddcc9943e3995894c5244Marc Blank Entity entity = setupTestEventEntity(organizer, attendee, title); 272dafc866120dac68fabbddcc9943e3995894c5244Marc Blank ContentValues entityValues = entity.getEntityValues(); 2739e86eb14c6e1f7d7730f8ca6953fdfd95fe2b143RoboErik entityValues.put(Events.ORIGINAL_SYNC_ID, 69); 274dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // The exception will be on April 26th 275dafc866120dac68fabbddcc9943e3995894c5244Marc Blank entityValues.put(Events.ORIGINAL_INSTANCE_TIME, 276dafc866120dac68fabbddcc9943e3995894c5244Marc Blank Utility.parseEmailDateTimeToMillis("2010-04-26T18:30:00Z")); 277dafc866120dac68fabbddcc9943e3995894c5244Marc Blank return entity; 278dafc866120dac68fabbddcc9943e3995894c5244Marc Blank } 279dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 2801c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank public void testCreateMessageForEntity_Reply() { 2811c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Set up the "event" 2821c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank String title = "Discuss Unit Tests"; 2839ca8918b82221dd441293973ffb84d565a52993aMarc Blank Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title); 2845c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 2851c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Create a dummy account for the attendee 2861c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank Account account = new Account(); 2879ca8918b82221dd441293973ffb84d565a52993aMarc Blank account.mEmailAddress = ATTENDEE; 2885c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 2891c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // The uid is required, but can be anything 2901c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank String uid = "31415926535"; 2911c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 2925c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank // Create the outgoing message 2935c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank Message msg = CalendarUtilities.createMessageForEntity(mContext, entity, 2945c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank Message.FLAG_OUTGOING_MEETING_ACCEPT, uid, account); 2955c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 2965c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank // First, we should have a message 2975c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank assertNotNull(msg); 2985c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 2995c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank // Now check some of the fields of the message 3009ca8918b82221dd441293973ffb84d565a52993aMarc Blank assertEquals(Address.pack(new Address[] {new Address(ORGANIZER)}), msg.mTo); 30100702b7e577ff2b7b1ae3f6dceefc615ba9cba72Marc Blank Resources resources = getContext().getResources(); 30200702b7e577ff2b7b1ae3f6dceefc615ba9cba72Marc Blank String accept = resources.getString(R.string.meeting_accepted, title); 303820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertEquals(accept, msg.mSubject); 30400702b7e577ff2b7b1ae3f6dceefc615ba9cba72Marc Blank assertNotNull(msg.mText); 30500702b7e577ff2b7b1ae3f6dceefc615ba9cba72Marc Blank assertTrue(msg.mText.contains(resources.getString(R.string.meeting_where, ""))); 3065c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 3075c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank // And make sure we have an attachment 3085c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank assertNotNull(msg.mAttachments); 3095c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank assertEquals(1, msg.mAttachments.size()); 3105c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank Attachment att = msg.mAttachments.get(0); 3115c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank // And that the attachment has the correct elements 3125c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank assertEquals("invite.ics", att.mFileName); 313b4d217e5170ae397d741e95308d98e80d0c2f637Marc Blank assertEquals(Attachment.FLAG_ICS_ALTERNATIVE_PART, 314b4d217e5170ae397d741e95308d98e80d0c2f637Marc Blank att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART); 3155c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank assertEquals("text/calendar; method=REPLY", att.mMimeType); 316e54b75dc4f638e594e9b97e3b4ed8829fbc9b521Makoto Onuki assertNotNull(att.mContentBytes); 317e54b75dc4f638e594e9b97e3b4ed8829fbc9b521Makoto Onuki assertEquals(att.mSize, att.mContentBytes.length); 3185c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 3195c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank //TODO Check the contents of the attachment using an iCalendar parser 3205c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank } 3215c6e14ab2f2e4c5dfc97cdeaedcc105159a9f29cMarc Blank 322c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank public void testCreateMessageForEntity_Invite_AllDay() throws IOException { 323c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // Set up the "event" 324c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank String title = "Discuss Unit Tests"; 325c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title); 32689bee1e3d03b439f4084bc9962bb3cbffd0b878aMarc Blank ContentValues entityValues = entity.getEntityValues(); 32789bee1e3d03b439f4084bc9962bb3cbffd0b878aMarc Blank entityValues.put(Events.ALL_DAY, 1); 32889bee1e3d03b439f4084bc9962bb3cbffd0b878aMarc Blank entityValues.put(Events.DURATION, "P1D"); 32989bee1e3d03b439f4084bc9962bb3cbffd0b878aMarc Blank entityValues.remove(Events.DTEND); 330c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 331c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // Create a dummy account for the attendee 332c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank Account account = new Account(); 333c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank account.mEmailAddress = ORGANIZER; 334c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 335c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // The uid is required, but can be anything 336c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank String uid = "31415926535"; 337c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 338c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // Create the outgoing message 339c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank Message msg = CalendarUtilities.createMessageForEntity(mContext, entity, 340c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank Message.FLAG_OUTGOING_MEETING_INVITE, uid, account); 341c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 342c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // First, we should have a message 343c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertNotNull(msg); 344c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 345c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // Now check some of the fields of the message 346c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals(Address.pack(new Address[] {new Address(ATTENDEE)}), msg.mTo); 34746e18bd76629be0835a5d5e6c839b6daac6cdfdcMarc Blank assertEquals(title, msg.mSubject); 348c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 349c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // And make sure we have an attachment 350c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertNotNull(msg.mAttachments); 351c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals(1, msg.mAttachments.size()); 352c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank Attachment att = msg.mAttachments.get(0); 353c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // And that the attachment has the correct elements 354c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals("invite.ics", att.mFileName); 355c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals(Attachment.FLAG_ICS_ALTERNATIVE_PART, 356c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART); 357c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals("text/calendar; method=REQUEST", att.mMimeType); 358c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertNotNull(att.mContentBytes); 359c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals(att.mSize, att.mContentBytes.length); 360c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 361c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // We'll check the contents of the ics file here 362c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank BlockHash vcalendar = parseIcsContent(att.mContentBytes); 363c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertNotNull(vcalendar); 364c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 365c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // We should have a VCALENDAR with a REQUEST method 366c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals("VCALENDAR", vcalendar.name); 367c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals("REQUEST", vcalendar.get("METHOD")); 368c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 369c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // We should have one block under VCALENDAR 370c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals(1, vcalendar.blocks.size()); 371c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank BlockHash vevent = vcalendar.blocks.get(0); 372c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // It's a VEVENT with the following fields 373c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals("VEVENT", vevent.name); 374c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals("Meeting Location", vevent.get("LOCATION")); 375c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals("0", vevent.get("SEQUENCE")); 376c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals("Discuss Unit Tests", vevent.get("SUMMARY")); 377c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals(uid, vevent.get("UID")); 378c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals("MAILTO:" + ATTENDEE, 379c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank vevent.get("ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE")); 380c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 381c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // These next two fields should have a date only 382c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals("20100412", vevent.get("DTSTART;VALUE=DATE")); 38389bee1e3d03b439f4084bc9962bb3cbffd0b878aMarc Blank assertEquals("20100413", vevent.get("DTEND;VALUE=DATE")); 384c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // This should be set to TRUE for all-day events 385c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals("TRUE", vevent.get("X-MICROSOFT-CDO-ALLDAYEVENT")); 386c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank } 387c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 3881c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank public void testCreateMessageForEntity_Invite() throws IOException { 3891c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Set up the "event" 3901c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank String title = "Discuss Unit Tests"; 3919ca8918b82221dd441293973ffb84d565a52993aMarc Blank Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title); 3921c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 3931c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Create a dummy account for the attendee 3941c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank Account account = new Account(); 3959ca8918b82221dd441293973ffb84d565a52993aMarc Blank account.mEmailAddress = ORGANIZER; 3961c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 3971c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // The uid is required, but can be anything 3981c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank String uid = "31415926535"; 3991c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 4001c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Create the outgoing message 4011c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank Message msg = CalendarUtilities.createMessageForEntity(mContext, entity, 4021c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank Message.FLAG_OUTGOING_MEETING_INVITE, uid, account); 4031c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 4041c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // First, we should have a message 4051c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertNotNull(msg); 4061c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 4071c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Now check some of the fields of the message 4089ca8918b82221dd441293973ffb84d565a52993aMarc Blank assertEquals(Address.pack(new Address[] {new Address(ATTENDEE)}), msg.mTo); 40946e18bd76629be0835a5d5e6c839b6daac6cdfdcMarc Blank assertEquals(title, msg.mSubject); 4101c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 4111c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // And make sure we have an attachment 4121c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertNotNull(msg.mAttachments); 4131c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertEquals(1, msg.mAttachments.size()); 4141c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank Attachment att = msg.mAttachments.get(0); 4151c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // And that the attachment has the correct elements 4161c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertEquals("invite.ics", att.mFileName); 417b4d217e5170ae397d741e95308d98e80d0c2f637Marc Blank assertEquals(Attachment.FLAG_ICS_ALTERNATIVE_PART, 418b4d217e5170ae397d741e95308d98e80d0c2f637Marc Blank att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART); 4191c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertEquals("text/calendar; method=REQUEST", att.mMimeType); 420e54b75dc4f638e594e9b97e3b4ed8829fbc9b521Makoto Onuki assertNotNull(att.mContentBytes); 421e54b75dc4f638e594e9b97e3b4ed8829fbc9b521Makoto Onuki assertEquals(att.mSize, att.mContentBytes.length); 4221c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 4231c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // We'll check the contents of the ics file here 424e54b75dc4f638e594e9b97e3b4ed8829fbc9b521Makoto Onuki BlockHash vcalendar = parseIcsContent(att.mContentBytes); 4251c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertNotNull(vcalendar); 4261c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 4271c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // We should have a VCALENDAR with a REQUEST method 4281c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertEquals("VCALENDAR", vcalendar.name); 4291c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertEquals("REQUEST", vcalendar.get("METHOD")); 4301c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 4311c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // We should have one block under VCALENDAR 4321c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertEquals(1, vcalendar.blocks.size()); 4331c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank BlockHash vevent = vcalendar.blocks.get(0); 4341c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // It's a VEVENT with the following fields 4351c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertEquals("VEVENT", vevent.name); 4361c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertEquals("Meeting Location", vevent.get("LOCATION")); 4371c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertEquals("0", vevent.get("SEQUENCE")); 4381c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertEquals("Discuss Unit Tests", vevent.get("SUMMARY")); 4391c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank assertEquals(uid, vevent.get("UID")); 4409ca8918b82221dd441293973ffb84d565a52993aMarc Blank assertEquals("MAILTO:" + ATTENDEE, 4411c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank vevent.get("ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE")); 442c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank 443c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // These next two fields should exist (without the VALUE=DATE suffix) 444c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertNotNull(vevent.get("DTSTART")); 445c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertNotNull(vevent.get("DTEND")); 446c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertNull(vevent.get("DTSTART;VALUE=DATE")); 447c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertNull(vevent.get("DTEND;VALUE=DATE")); 448c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank // This shouldn't exist for this event 449c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertNull(vevent.get("X-MICROSOFT-CDO-ALLDAYEVENT")); 4501c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 4511c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 45267010d38cb168666b34431c96f331f36507e1f03Marc Blank public void testCreateMessageForEntity_Recurring() throws IOException { 45367010d38cb168666b34431c96f331f36507e1f03Marc Blank // Set up the "event" 45467010d38cb168666b34431c96f331f36507e1f03Marc Blank String title = "Discuss Unit Tests"; 45567010d38cb168666b34431c96f331f36507e1f03Marc Blank Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title); 45667010d38cb168666b34431c96f331f36507e1f03Marc Blank // Set up a RRULE for this event 45767010d38cb168666b34431c96f331f36507e1f03Marc Blank entity.getEntityValues().put(Events.RRULE, "FREQ=DAILY"); 45867010d38cb168666b34431c96f331f36507e1f03Marc Blank 45967010d38cb168666b34431c96f331f36507e1f03Marc Blank // Create a dummy account for the attendee 46067010d38cb168666b34431c96f331f36507e1f03Marc Blank Account account = new Account(); 46167010d38cb168666b34431c96f331f36507e1f03Marc Blank account.mEmailAddress = ORGANIZER; 46267010d38cb168666b34431c96f331f36507e1f03Marc Blank 46367010d38cb168666b34431c96f331f36507e1f03Marc Blank // The uid is required, but can be anything 46467010d38cb168666b34431c96f331f36507e1f03Marc Blank String uid = "31415926535"; 46567010d38cb168666b34431c96f331f36507e1f03Marc Blank 46667010d38cb168666b34431c96f331f36507e1f03Marc Blank // Create the outgoing message 46767010d38cb168666b34431c96f331f36507e1f03Marc Blank Message msg = CalendarUtilities.createMessageForEntity(mContext, entity, 46867010d38cb168666b34431c96f331f36507e1f03Marc Blank Message.FLAG_OUTGOING_MEETING_INVITE, uid, account); 46967010d38cb168666b34431c96f331f36507e1f03Marc Blank 47067010d38cb168666b34431c96f331f36507e1f03Marc Blank // First, we should have a message 47167010d38cb168666b34431c96f331f36507e1f03Marc Blank assertNotNull(msg); 47267010d38cb168666b34431c96f331f36507e1f03Marc Blank 47367010d38cb168666b34431c96f331f36507e1f03Marc Blank // Now check some of the fields of the message 47467010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals(Address.pack(new Address[] {new Address(ATTENDEE)}), msg.mTo); 47567010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals(title, msg.mSubject); 47667010d38cb168666b34431c96f331f36507e1f03Marc Blank 47767010d38cb168666b34431c96f331f36507e1f03Marc Blank // And make sure we have an attachment 47867010d38cb168666b34431c96f331f36507e1f03Marc Blank assertNotNull(msg.mAttachments); 47967010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals(1, msg.mAttachments.size()); 48067010d38cb168666b34431c96f331f36507e1f03Marc Blank Attachment att = msg.mAttachments.get(0); 48167010d38cb168666b34431c96f331f36507e1f03Marc Blank // And that the attachment has the correct elements 48267010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals("invite.ics", att.mFileName); 48367010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals(Attachment.FLAG_ICS_ALTERNATIVE_PART, 48467010d38cb168666b34431c96f331f36507e1f03Marc Blank att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART); 48567010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals("text/calendar; method=REQUEST", att.mMimeType); 48667010d38cb168666b34431c96f331f36507e1f03Marc Blank assertNotNull(att.mContentBytes); 48767010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals(att.mSize, att.mContentBytes.length); 48867010d38cb168666b34431c96f331f36507e1f03Marc Blank 48967010d38cb168666b34431c96f331f36507e1f03Marc Blank // We'll check the contents of the ics file here 49067010d38cb168666b34431c96f331f36507e1f03Marc Blank BlockHash vcalendar = parseIcsContent(att.mContentBytes); 49167010d38cb168666b34431c96f331f36507e1f03Marc Blank assertNotNull(vcalendar); 49267010d38cb168666b34431c96f331f36507e1f03Marc Blank 49367010d38cb168666b34431c96f331f36507e1f03Marc Blank // We should have a VCALENDAR with a REQUEST method 49467010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals("VCALENDAR", vcalendar.name); 49567010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals("REQUEST", vcalendar.get("METHOD")); 49667010d38cb168666b34431c96f331f36507e1f03Marc Blank 49767010d38cb168666b34431c96f331f36507e1f03Marc Blank // We should have two blocks under VCALENDAR (VTIMEZONE and VEVENT) 49867010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals(2, vcalendar.blocks.size()); 49967010d38cb168666b34431c96f331f36507e1f03Marc Blank 50067010d38cb168666b34431c96f331f36507e1f03Marc Blank // This is the time zone that should be used 50167010d38cb168666b34431c96f331f36507e1f03Marc Blank TimeZone timeZone = TimeZone.getDefault(); 50267010d38cb168666b34431c96f331f36507e1f03Marc Blank 50367010d38cb168666b34431c96f331f36507e1f03Marc Blank BlockHash vtimezone = vcalendar.blocks.get(0); 50467010d38cb168666b34431c96f331f36507e1f03Marc Blank // It should be a VTIMEZONE for timeZone 50567010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals("VTIMEZONE", vtimezone.name); 50667010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals(timeZone.getID(), vtimezone.get("TZID")); 50767010d38cb168666b34431c96f331f36507e1f03Marc Blank 50867010d38cb168666b34431c96f331f36507e1f03Marc Blank BlockHash vevent = vcalendar.blocks.get(1); 50967010d38cb168666b34431c96f331f36507e1f03Marc Blank // It's a VEVENT with the following fields 51067010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals("VEVENT", vevent.name); 51167010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals("Meeting Location", vevent.get("LOCATION")); 51267010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals("0", vevent.get("SEQUENCE")); 51367010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals("Discuss Unit Tests", vevent.get("SUMMARY")); 51467010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals(uid, vevent.get("UID")); 51567010d38cb168666b34431c96f331f36507e1f03Marc Blank assertEquals("MAILTO:" + ATTENDEE, 51667010d38cb168666b34431c96f331f36507e1f03Marc Blank vevent.get("ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE")); 51767010d38cb168666b34431c96f331f36507e1f03Marc Blank 51867010d38cb168666b34431c96f331f36507e1f03Marc Blank // We should have DTSTART/DTEND with time zone 51967010d38cb168666b34431c96f331f36507e1f03Marc Blank assertNotNull(vevent.get("DTSTART;TZID=" + timeZone.getID())); 52067010d38cb168666b34431c96f331f36507e1f03Marc Blank assertNotNull(vevent.get("DTEND;TZID=" + timeZone.getID())); 52167010d38cb168666b34431c96f331f36507e1f03Marc Blank assertNull(vevent.get("DTSTART")); 52267010d38cb168666b34431c96f331f36507e1f03Marc Blank assertNull(vevent.get("DTEND")); 52367010d38cb168666b34431c96f331f36507e1f03Marc Blank assertNull(vevent.get("DTSTART;VALUE=DATE")); 52467010d38cb168666b34431c96f331f36507e1f03Marc Blank assertNull(vevent.get("DTEND;VALUE=DATE")); 52567010d38cb168666b34431c96f331f36507e1f03Marc Blank // This shouldn't exist for this event 52667010d38cb168666b34431c96f331f36507e1f03Marc Blank assertNull(vevent.get("X-MICROSOFT-CDO-ALLDAYEVENT")); 52767010d38cb168666b34431c96f331f36507e1f03Marc Blank } 52867010d38cb168666b34431c96f331f36507e1f03Marc Blank 529dafc866120dac68fabbddcc9943e3995894c5244Marc Blank public void testCreateMessageForEntity_Exception_Cancel() throws IOException { 530dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // Set up the "exception"... 531dafc866120dac68fabbddcc9943e3995894c5244Marc Blank String title = "Discuss Unit Tests"; 5329ca8918b82221dd441293973ffb84d565a52993aMarc Blank Entity entity = setupTestExceptionEntity(ORGANIZER, ATTENDEE, title); 533dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 534dafc866120dac68fabbddcc9943e3995894c5244Marc Blank ContentValues entityValues = entity.getEntityValues(); 535dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // Mark the Exception as dirty 5369e86eb14c6e1f7d7730f8ca6953fdfd95fe2b143RoboErik entityValues.put(Events.DIRTY, 1); 537dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // And mark it canceled 538dafc866120dac68fabbddcc9943e3995894c5244Marc Blank entityValues.put(Events.STATUS, Events.STATUS_CANCELED); 539dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 540dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // Create a dummy account for the attendee 541dafc866120dac68fabbddcc9943e3995894c5244Marc Blank Account account = new Account(); 5429ca8918b82221dd441293973ffb84d565a52993aMarc Blank account.mEmailAddress = ORGANIZER; 543dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 544dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // The uid is required, but can be anything 545dafc866120dac68fabbddcc9943e3995894c5244Marc Blank String uid = "31415926535"; 546dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 547dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // Create the outgoing message 548dafc866120dac68fabbddcc9943e3995894c5244Marc Blank Message msg = CalendarUtilities.createMessageForEntity(mContext, entity, 549bf1de871b7ec63c93694ba022282e8789e69f201Marc Blank Message.FLAG_OUTGOING_MEETING_CANCEL, uid, account); 550dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 551dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // First, we should have a message 552dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertNotNull(msg); 553dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 554dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // Now check some of the fields of the message 5559ca8918b82221dd441293973ffb84d565a52993aMarc Blank assertEquals(Address.pack(new Address[] {new Address(ATTENDEE)}), msg.mTo); 556bf1de871b7ec63c93694ba022282e8789e69f201Marc Blank String cancel = getContext().getResources().getString(R.string.meeting_canceled, title); 557bf1de871b7ec63c93694ba022282e8789e69f201Marc Blank assertEquals(cancel, msg.mSubject); 558dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 559dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // And make sure we have an attachment 560dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertNotNull(msg.mAttachments); 561dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertEquals(1, msg.mAttachments.size()); 562dafc866120dac68fabbddcc9943e3995894c5244Marc Blank Attachment att = msg.mAttachments.get(0); 563dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // And that the attachment has the correct elements 564dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertEquals("invite.ics", att.mFileName); 565b4d217e5170ae397d741e95308d98e80d0c2f637Marc Blank assertEquals(Attachment.FLAG_ICS_ALTERNATIVE_PART, 566b4d217e5170ae397d741e95308d98e80d0c2f637Marc Blank att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART); 567f58e3ba6e6e246a804e6908c831a43b46a61bc07Marc Blank assertEquals("text/calendar; method=CANCEL", att.mMimeType); 568e54b75dc4f638e594e9b97e3b4ed8829fbc9b521Makoto Onuki assertNotNull(att.mContentBytes); 569dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 570dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // We'll check the contents of the ics file here 571e54b75dc4f638e594e9b97e3b4ed8829fbc9b521Makoto Onuki BlockHash vcalendar = parseIcsContent(att.mContentBytes); 572dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertNotNull(vcalendar); 573dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 574f58e3ba6e6e246a804e6908c831a43b46a61bc07Marc Blank // We should have a VCALENDAR with a CANCEL method 575dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertEquals("VCALENDAR", vcalendar.name); 576f58e3ba6e6e246a804e6908c831a43b46a61bc07Marc Blank assertEquals("CANCEL", vcalendar.get("METHOD")); 577dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 578dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // This is the time zone that should be used 579dafc866120dac68fabbddcc9943e3995894c5244Marc Blank TimeZone timeZone = TimeZone.getDefault(); 580dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 581dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // We should have two blocks under VCALENDAR (VTIMEZONE and VEVENT) 582dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertEquals(2, vcalendar.blocks.size()); 583dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 584dafc866120dac68fabbddcc9943e3995894c5244Marc Blank BlockHash vtimezone = vcalendar.blocks.get(0); 585dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // It should be a VTIMEZONE for timeZone 586dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertEquals("VTIMEZONE", vtimezone.name); 587dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertEquals(timeZone.getID(), vtimezone.get("TZID")); 588dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 589dafc866120dac68fabbddcc9943e3995894c5244Marc Blank BlockHash vevent = vcalendar.blocks.get(1); 590dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // It's a VEVENT with the following fields 591dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertEquals("VEVENT", vevent.name); 592dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertEquals("Meeting Location", vevent.get("LOCATION")); 593dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertEquals("0", vevent.get("SEQUENCE")); 594dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertEquals("Discuss Unit Tests", vevent.get("SUMMARY")); 595dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertEquals(uid, vevent.get("UID")); 5969ca8918b82221dd441293973ffb84d565a52993aMarc Blank assertEquals("MAILTO:" + ATTENDEE, 597bf1de871b7ec63c93694ba022282e8789e69f201Marc Blank vevent.get("ATTENDEE;ROLE=REQ-PARTICIPANT")); 598dafc866120dac68fabbddcc9943e3995894c5244Marc Blank long originalTime = entityValues.getAsLong(Events.ORIGINAL_INSTANCE_TIME); 599dafc866120dac68fabbddcc9943e3995894c5244Marc Blank assertNotSame(0, originalTime); 600dafc866120dac68fabbddcc9943e3995894c5244Marc Blank // For an exception, RECURRENCE-ID is critical 601c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank assertEquals(CalendarUtilities.millisToEasDateTime(originalTime, timeZone, 602c1b63a27ed05bed70f74cf33fe08f8bd1f0d745fMarc Blank true /*withTime*/), vevent.get("RECURRENCE-ID" + ";TZID=" + timeZone.getID())); 603dafc866120dac68fabbddcc9943e3995894c5244Marc Blank } 604dafc866120dac68fabbddcc9943e3995894c5244Marc Blank 605820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank public void testUtcOffsetString() { 606820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertEquals(CalendarUtilities.utcOffsetString(540), "+0900"); 607820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertEquals(CalendarUtilities.utcOffsetString(-480), "-0800"); 608820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertEquals(CalendarUtilities.utcOffsetString(0), "+0000"); 609820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank } 6101c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 611820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank public void testFindTransitionDate() { 612820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // We'll find some transitions and make sure that we're properly in or out of daylight time 613820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // on either side of the transition. 614820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Use CST for testing (any other will do as well, as long as it has DST) 615820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank TimeZone tz = TimeZone.getTimeZone("US/Central"); 616ee8c9a284b160f353e3bd918aafbc7ed528bfc4cMarc Blank // Confirm that this time zone uses DST 617ee8c9a284b160f353e3bd918aafbc7ed528bfc4cMarc Blank assertTrue(tz.useDaylightTime()); 618820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Get a calendar at January 1st of the current year 619820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank GregorianCalendar calendar = new GregorianCalendar(tz); 620820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank calendar.set(CalendarUtilities.sCurrentYear, Calendar.JANUARY, 1); 621820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Get start and end times at start and end of year 622820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank long startTime = calendar.getTimeInMillis(); 623820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank long endTime = startTime + (365*CalendarUtilities.DAYS); 624820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Find the first transition 625820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank GregorianCalendar transitionCalendar = 626820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank CalendarUtilities.findTransitionDate(tz, startTime, endTime, false); 627820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank long transitionTime = transitionCalendar.getTimeInMillis(); 628820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Before should be in standard time; after in daylight time 629820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank Date beforeDate = new Date(transitionTime - CalendarUtilities.HOURS); 630820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank Date afterDate = new Date(transitionTime + CalendarUtilities.HOURS); 631820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertFalse(tz.inDaylightTime(beforeDate)); 632820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertTrue(tz.inDaylightTime(afterDate)); 633820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank 634820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Find the next one... 635820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank transitionCalendar = CalendarUtilities.findTransitionDate(tz, transitionTime + 636820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank CalendarUtilities.DAYS, endTime, true); 637820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank transitionTime = transitionCalendar.getTimeInMillis(); 638820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // This time, Before should be in daylight time; after in standard time 639820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank beforeDate = new Date(transitionTime - CalendarUtilities.HOURS); 640820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank afterDate = new Date(transitionTime + CalendarUtilities.HOURS); 641820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertTrue(tz.inDaylightTime(beforeDate)); 642820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertFalse(tz.inDaylightTime(afterDate)); 643820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank 644ee8c9a284b160f353e3bd918aafbc7ed528bfc4cMarc Blank // Kinshasa has no daylight savings time 645ee8c9a284b160f353e3bd918aafbc7ed528bfc4cMarc Blank tz = TimeZone.getTimeZone("Africa/Kinshasa"); 646ee8c9a284b160f353e3bd918aafbc7ed528bfc4cMarc Blank // Confirm that there's no DST for this time zone 647ee8c9a284b160f353e3bd918aafbc7ed528bfc4cMarc Blank assertFalse(tz.useDaylightTime()); 648820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Get a calendar at January 1st of the current year 649820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank calendar = new GregorianCalendar(tz); 650820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank calendar.set(CalendarUtilities.sCurrentYear, Calendar.JANUARY, 1); 651820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Get start and end times at start and end of year 652820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank startTime = calendar.getTimeInMillis(); 653820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank endTime = startTime + (365*CalendarUtilities.DAYS); 654820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Find the first transition 655820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank transitionCalendar = CalendarUtilities.findTransitionDate(tz, startTime, endTime, false); 656820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // There had better not be one 657820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertNull(transitionCalendar); 658820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank } 659377230593dca7cb01483bfaf93959e5821f5f028Marc Blank 660820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank public void testRruleFromRecurrence() { 661820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Every Monday for 2 weeks 662820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank String rrule = CalendarUtilities.rruleFromRecurrence( 663820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank 1 /*Weekly*/, 2 /*Occurrences*/, 1 /*Interval*/, 2 /*Monday*/, 0, 0, 0, null); 664f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank assertEquals("FREQ=WEEKLY;COUNT=2;INTERVAL=1;BYDAY=MO", rrule); 665820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Every Tuesday and Friday 666820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank rrule = CalendarUtilities.rruleFromRecurrence( 667820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank 1 /*Weekly*/, 0 /*Occurrences*/, 0 /*Interval*/, 36 /*Tue&Fri*/, 0, 0, 0, null); 668820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertEquals("FREQ=WEEKLY;BYDAY=TU,FR", rrule); 669820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // The last Saturday of the month 670820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank rrule = CalendarUtilities.rruleFromRecurrence( 671f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank 1 /*Weekly*/, 0, 0, 64 /*Sat*/, 0, 5 /*Last*/, 0, null); 672f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank assertEquals("FREQ=WEEKLY;BYDAY=-1SA", rrule); 673820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // The third Wednesday and Thursday of the month 674820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank rrule = CalendarUtilities.rruleFromRecurrence( 675f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank 1 /*Weekly*/, 0, 0, 24 /*Wed&Thu*/, 0, 3 /*3rd*/, 0, null); 676f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank assertEquals("FREQ=WEEKLY;BYDAY=3WE,3TH", rrule); 677f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank rrule = CalendarUtilities.rruleFromRecurrence( 678f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank 3 /*Monthly/Day*/, 0, 0, 127 /*LastDay*/, 0, 0, 0, null); 679f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank assertEquals("FREQ=MONTHLY;BYMONTHDAY=-1", rrule); 680f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank rrule = CalendarUtilities.rruleFromRecurrence( 681f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank 3 /*Monthly/Day*/, 0, 0, 62 /*M-F*/, 0, 5 /*Last week*/, 0, null); 682f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank assertEquals("FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1", rrule); 683820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // The 14th of the every month 684820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank rrule = CalendarUtilities.rruleFromRecurrence( 685820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank 2 /*Monthly/Date*/, 0, 0, 0, 14 /*14th*/, 0, 0, null); 686820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertEquals("FREQ=MONTHLY;BYMONTHDAY=14", rrule); 687820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // Every 31st of October 688820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank rrule = CalendarUtilities.rruleFromRecurrence( 689820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank 5 /*Yearly/Date*/, 0, 0, 0, 31 /*31st*/, 0, 10 /*October*/, null); 690820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertEquals("FREQ=YEARLY;BYMONTHDAY=31;BYMONTH=10", rrule); 691820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank // The first Tuesday of June 692820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank rrule = CalendarUtilities.rruleFromRecurrence( 693820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank 6 /*Yearly/Month/DayOfWeek*/, 0, 0, 4 /*Tue*/, 0, 1 /*1st*/, 6 /*June*/, null); 694820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank assertEquals("FREQ=YEARLY;BYDAY=1TU;BYMONTH=6", rrule); 695820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank } 696820dbc5ff3497fdd98fdb1cc42c1d298f9c1f199Marc Blank 6971c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank /** 698f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank * Given a CalendarSyncAdapter and an RRULE, serialize the RRULE via recurrentFromRrule and 699f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank * then parse the result. Assert that the resulting RRULE is the same as the original. 700f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank * @param adapter a CalendarSyncAdapter 701f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank * @param rrule an RRULE string that will be tested 702f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank * @throws IOException 703f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank */ 704f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank private void testSingleRecurrenceFromRrule(CalendarSyncAdapter adapter, String rrule) 705f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank throws IOException { 706f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank Serializer s = new Serializer(); 707f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank CalendarUtilities.recurrenceFromRrule(rrule, 0, s); 708f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank s.done(); 709f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank EasCalendarSyncParser parser = adapter.new EasCalendarSyncParser( 710f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank new ByteArrayInputStream(s.toByteArray()), adapter); 711f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank // The first element should be the outer CALENDAR_RECURRENCE tag 712f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank assertEquals(Tags.CALENDAR_RECURRENCE, parser.nextTag(Parser.START_DOCUMENT)); 713f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank assertEquals(rrule, parser.recurrenceParser()); 714f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank } 715f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank 716f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank /** 717f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank * Round-trip test of RRULE handling; we serialize an RRULE and then parse the result; the 718f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank * result should be identical to the original RRULE 719f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank */ 720f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank public void testRecurrenceFromRrule() throws IOException { 721f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank // A test sync adapter we can use throughout the test 722f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank CalendarSyncAdapter adapter = getTestSyncAdapter(CalendarSyncAdapter.class); 723f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank 724f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank testSingleRecurrenceFromRrule(adapter, "FREQ=WEEKLY;COUNT=2;INTERVAL=1;BYDAY=MO"); 725f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank testSingleRecurrenceFromRrule(adapter, "FREQ=WEEKLY;BYDAY=TU,FR"); 726f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank testSingleRecurrenceFromRrule(adapter, "FREQ=WEEKLY;BYDAY=-1SA"); 727f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank testSingleRecurrenceFromRrule(adapter, "FREQ=WEEKLY;BYDAY=3WE,3TH"); 728f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank testSingleRecurrenceFromRrule(adapter, "FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1"); 729f352bc9f29cacc61b195069e48d5c8b868660694Marc Blank testSingleRecurrenceFromRrule(adapter, "FREQ=MONTHLY;BYMONTHDAY=17"); 730f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank testSingleRecurrenceFromRrule(adapter, "FREQ=YEARLY;BYMONTHDAY=31;BYMONTH=10"); 731f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank testSingleRecurrenceFromRrule(adapter, "FREQ=YEARLY;BYDAY=1TU;BYMONTH=6"); 732f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank } 733f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank 734f72b4bc0ea714067ae528e63c916f0237d2202e6Marc Blank /** 7351c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank * For debugging purposes, to help keep track of parsing errors. 7361c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank */ 7371c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank private class UnterminatedBlockException extends IOException { 7381c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank private static final long serialVersionUID = 1L; 7391c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank UnterminatedBlockException(String name) { 7401c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank super(name); 7411c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 7421c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 7431c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 7441c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank /** 7451c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank * A lightweight representation of block object containing a hash of individual values and an 7461c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank * array of inner blocks. The object is build by pulling elements from a BufferedReader. 7471c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank * NOTE: Multiple values of a given field are not supported. We'd see this with ATTENDEEs, for 7481c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank * example, and possibly RDATEs in VTIMEZONEs without an RRULE; these cases will be handled 7491c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank * at a later time. 7501c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank */ 7511c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank private class BlockHash { 7521c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank String name; 7531c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank HashMap<String, String> hash = new HashMap<String, String>(); 7541c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank ArrayList<BlockHash> blocks = new ArrayList<BlockHash>(); 7551c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 7561c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank BlockHash (String _name, BufferedReader reader) throws IOException { 7571c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank name = _name; 7581c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank String lastField = null; 7591c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank String lastValue = null; 7601c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank while (true) { 7611c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Get a line; we're done if it's null 7621c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank String line = reader.readLine(); 7631c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank if (line == null) { 7641c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank throw new UnterminatedBlockException(name); 7651c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 7661c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank int length = line.length(); 7671c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank if (length == 0) { 7681c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // We shouldn't ever see an empty line 7691c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank throw new IllegalArgumentException(); 7701c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 771bc0c8c1523fc0bc42eb82dba6c2977492e441c03Makoto Onuki // A line starting with tab is a continuation 772bc0c8c1523fc0bc42eb82dba6c2977492e441c03Makoto Onuki if (line.charAt(0) == '\t') { 7731c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Remember the line and length 7741c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank lastValue = line.substring(1); 7751c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Save the concatenation of old and new values 7761c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank hash.put(lastField, hash.get(lastField) + lastValue); 7771c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank continue; 7781c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 7791c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Find the field delimiter 7801c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank int pos = line.indexOf(':'); 7811c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // If not found, or at EOL, this is a bad ics 7821c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank if (pos < 0 || pos >= length) { 7831c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank throw new IllegalArgumentException(); 7841c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 7851c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Remember the field, value, and length 7861c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank lastField = line.substring(0, pos); 7871c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank lastValue = line.substring(pos + 1); 7881c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank if (lastField.equals("BEGIN")) { 7891c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank blocks.add(new BlockHash(lastValue, reader)); 7901c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank continue; 7911c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } else if (lastField.equals("END")) { 7921c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank if (!lastValue.equals(name)) { 7931c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank throw new UnterminatedBlockException(name); 7941c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 7951c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank break; 7961c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 7971c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 7981c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank // Save it away and continue 7991c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank hash.put(lastField, lastValue); 8001c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 8011c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 8021c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 8031c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank String get(String field) { 8041c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank return hash.get(field); 8051c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 8061c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 8071c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 808e54b75dc4f638e594e9b97e3b4ed8829fbc9b521Makoto Onuki private BlockHash parseIcsContent(byte[] bytes) throws IOException { 809d38b4e9c1893a6c4ac70c08c5211629da3840cb2Makoto Onuki BufferedReader reader = new BufferedReader(new StringReader(Utility.fromUtf8(bytes))); 8101c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank String line = reader.readLine(); 8111c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank if (!line.equals("BEGIN:VCALENDAR")) { 8121c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank throw new IllegalArgumentException(); 8131c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 8141c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank return new BlockHash("VCALENDAR", reader); 8151c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank } 8161c9dfc1ce8d40b4a09fb6baf2fd9ed9c482b8900Marc Blank 8179ca8918b82221dd441293973ffb84d565a52993aMarc Blank public void testBuildMessageTextFromEntityValues() { 8189ca8918b82221dd441293973ffb84d565a52993aMarc Blank // Set up a test event 8199ca8918b82221dd441293973ffb84d565a52993aMarc Blank String title = "Event Title"; 8209ca8918b82221dd441293973ffb84d565a52993aMarc Blank Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title); 8219ca8918b82221dd441293973ffb84d565a52993aMarc Blank ContentValues entityValues = entity.getEntityValues(); 8229ca8918b82221dd441293973ffb84d565a52993aMarc Blank 8239ca8918b82221dd441293973ffb84d565a52993aMarc Blank // Save this away; we'll use it a few times below 8249ca8918b82221dd441293973ffb84d565a52993aMarc Blank Resources resources = mContext.getResources(); 8259ca8918b82221dd441293973ffb84d565a52993aMarc Blank Date date = new Date(entityValues.getAsLong(Events.DTSTART)); 8269ca8918b82221dd441293973ffb84d565a52993aMarc Blank String dateTimeString = DateFormat.getDateTimeInstance().format(date); 8279ca8918b82221dd441293973ffb84d565a52993aMarc Blank 8289ca8918b82221dd441293973ffb84d565a52993aMarc Blank // Get the text for this message 8299ca8918b82221dd441293973ffb84d565a52993aMarc Blank StringBuilder sb = new StringBuilder(); 8309ca8918b82221dd441293973ffb84d565a52993aMarc Blank CalendarUtilities.buildMessageTextFromEntityValues(mContext, entityValues, sb); 8319ca8918b82221dd441293973ffb84d565a52993aMarc Blank String text = sb.toString(); 8329ca8918b82221dd441293973ffb84d565a52993aMarc Blank // We'll just check the when and where 8339ca8918b82221dd441293973ffb84d565a52993aMarc Blank assertTrue(text.contains(resources.getString(R.string.meeting_when, dateTimeString))); 8349ca8918b82221dd441293973ffb84d565a52993aMarc Blank String location = entityValues.getAsString(Events.EVENT_LOCATION); 8359ca8918b82221dd441293973ffb84d565a52993aMarc Blank assertTrue(text.contains(resources.getString(R.string.meeting_where, location))); 8369ca8918b82221dd441293973ffb84d565a52993aMarc Blank 8379ca8918b82221dd441293973ffb84d565a52993aMarc Blank // Make this event recurring 8389ca8918b82221dd441293973ffb84d565a52993aMarc Blank entity.getEntityValues().put(Events.RRULE, "FREQ=WEEKLY;BYDAY=MO"); 8399ca8918b82221dd441293973ffb84d565a52993aMarc Blank sb = new StringBuilder(); 8409ca8918b82221dd441293973ffb84d565a52993aMarc Blank CalendarUtilities.buildMessageTextFromEntityValues(mContext, entityValues, sb); 8419ca8918b82221dd441293973ffb84d565a52993aMarc Blank text = sb.toString(); 8429ca8918b82221dd441293973ffb84d565a52993aMarc Blank assertTrue(text.contains(resources.getString(R.string.meeting_recurring, dateTimeString))); 8439ca8918b82221dd441293973ffb84d565a52993aMarc Blank } 8449ca8918b82221dd441293973ffb84d565a52993aMarc Blank 845879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank /** 846879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank * Sanity test for time zone generation. Most important, make sure that we can run through 847879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank * all of the time zones without generating an exception. Second, make sure that we're finding 848879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank * rules for at least 90% of time zones that use daylight time (empirically, it's more like 849879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank * 95%). Log those without rules. 850879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank * @throws IOException 851879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank */ 852879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank public void testTimeZoneToVTimezone() throws IOException { 853879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank SimpleIcsWriter writer = new SimpleIcsWriter(); 854879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank int rule = 0; 855879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank int nodst = 0; 856879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank int norule = 0; 857879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank ArrayList<String> norulelist = new ArrayList<String>(); 858879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank for (String tzs: TimeZone.getAvailableIDs()) { 859879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank TimeZone tz = TimeZone.getTimeZone(tzs); 860879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank writer = new SimpleIcsWriter(); 861879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank CalendarUtilities.timeZoneToVTimezone(tz, writer); 862879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank String vc = writer.toString(); 863879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank boolean hasRule = vc.indexOf("RRULE") > 0; 864879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank if (hasRule) { 865879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank rule++; 866879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank } else if (tz.useDaylightTime()) { 867879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank norule++; 868879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank norulelist.add(tz.getID()); 869879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank } else { 870879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank nodst++; 871879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank } 872879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank } 873879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank Log.d("TimeZoneGeneration", 874879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank "Rule: " + rule + ", No DST: " + nodst + ", No rule: " + norule); 875879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank for (String nr: norulelist) { 876879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank Log.d("TimeZoneGeneration", "No rule: " + nr); 877879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank } 878ee8c9a284b160f353e3bd918aafbc7ed528bfc4cMarc Blank // This is an empirical sanity test; we shouldn't have too many time zones with DST and 879ee8c9a284b160f353e3bd918aafbc7ed528bfc4cMarc Blank // without a rule. 880ee8c9a284b160f353e3bd918aafbc7ed528bfc4cMarc Blank assertTrue(norule < rule/8); 881879b4d7bd28de1c8bb8c8aba9c1ab17936d300aaMarc Blank } 882b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank 883b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank public void testGetUidFromGlobalObjId() { 884b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank // This is a "foreign" uid (from some vCalendar client) 885b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank String globalObjId = "BAAAAIIA4AB0xbcQGoLgCAAAAAAAAAAAAAAAAAAAAAAAAAAAMQAAA" + 886b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank "HZDYWwtVWlkAQAAADI3NjU1NmRkLTg1MzAtNGZiZS1iMzE0LThiM2JlYTYwMjE0OQA="; 887b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank String uid = CalendarUtilities.getUidFromGlobalObjId(globalObjId); 888b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank assertEquals(uid, "276556dd-8530-4fbe-b314-8b3bea602149"); 889b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank // This is a native EAS uid 890b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank globalObjId = 891b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank "BAAAAIIA4AB0xbcQGoLgCAAAAADACTu7KbPKAQAAAAAAAAAAEAAAAObgsG6HVt1Fmy+7GlLbGhY="; 892b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank uid = CalendarUtilities.getUidFromGlobalObjId(globalObjId); 893b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank assertEquals(uid, "040000008200E00074C5B7101A82E00800000000C0093BBB29B3CA" + 894b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank "01000000000000000010000000E6E0B06E8756DD459B2FBB1A52DB1A16"); 895b94d16528fc9c7f5dbb5c75c059f76cee2070c09Marc Blank } 896dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank 897dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank public void testSelfAttendeeStatusFromBusyStatus() { 898dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank assertEquals(Attendees.ATTENDEE_STATUS_ACCEPTED, 899edcfd554728a27a7678306ea7432bd8676ec6990Marc Blank CalendarUtilities.attendeeStatusFromBusyStatus( 900dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank CalendarUtilities.BUSY_STATUS_BUSY)); 901dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank assertEquals(Attendees.ATTENDEE_STATUS_TENTATIVE, 902edcfd554728a27a7678306ea7432bd8676ec6990Marc Blank CalendarUtilities.attendeeStatusFromBusyStatus( 903dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank CalendarUtilities.BUSY_STATUS_TENTATIVE)); 904dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank assertEquals(Attendees.ATTENDEE_STATUS_NONE, 905edcfd554728a27a7678306ea7432bd8676ec6990Marc Blank CalendarUtilities.attendeeStatusFromBusyStatus( 906dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank CalendarUtilities.BUSY_STATUS_FREE)); 907dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank assertEquals(Attendees.ATTENDEE_STATUS_NONE, 908edcfd554728a27a7678306ea7432bd8676ec6990Marc Blank CalendarUtilities.attendeeStatusFromBusyStatus( 909e51fedc3c055588a69da56d0b818ea12ed8f706fMarc Blank CalendarUtilities.BUSY_STATUS_OUT_OF_OFFICE)); 910dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank } 911dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank 912dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank public void testBusyStatusFromSelfStatus() { 913dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank assertEquals(CalendarUtilities.BUSY_STATUS_FREE, 914edcfd554728a27a7678306ea7432bd8676ec6990Marc Blank CalendarUtilities.busyStatusFromAttendeeStatus( 915dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank Attendees.ATTENDEE_STATUS_DECLINED)); 916e51fedc3c055588a69da56d0b818ea12ed8f706fMarc Blank assertEquals(CalendarUtilities.BUSY_STATUS_FREE, 917edcfd554728a27a7678306ea7432bd8676ec6990Marc Blank CalendarUtilities.busyStatusFromAttendeeStatus( 918dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank Attendees.ATTENDEE_STATUS_NONE)); 919e51fedc3c055588a69da56d0b818ea12ed8f706fMarc Blank assertEquals(CalendarUtilities.BUSY_STATUS_FREE, 920edcfd554728a27a7678306ea7432bd8676ec6990Marc Blank CalendarUtilities.busyStatusFromAttendeeStatus( 921dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank Attendees.ATTENDEE_STATUS_INVITED)); 922dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank assertEquals(CalendarUtilities.BUSY_STATUS_TENTATIVE, 923edcfd554728a27a7678306ea7432bd8676ec6990Marc Blank CalendarUtilities.busyStatusFromAttendeeStatus( 924dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank Attendees.ATTENDEE_STATUS_TENTATIVE)); 925dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank assertEquals(CalendarUtilities.BUSY_STATUS_BUSY, 926edcfd554728a27a7678306ea7432bd8676ec6990Marc Blank CalendarUtilities.busyStatusFromAttendeeStatus( 927dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank Attendees.ATTENDEE_STATUS_ACCEPTED)); 928dc27937dda50f991de9e12b98b80ee6aa3fe348eMarc Blank } 929270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank 930270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank public void testGetUtcAllDayCalendarTime() { 931270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank GregorianCalendar correctUtc = new GregorianCalendar(TimeZone.getTimeZone("UTC")); 932270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank correctUtc.set(2011, 2, 10, 0, 0, 0); 933270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank long correctUtcTime = correctUtc.getTimeInMillis(); 934270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank 935270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank TimeZone localTimeZone = TimeZone.getTimeZone("GMT-0700"); 936270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank GregorianCalendar localCalendar = new GregorianCalendar(localTimeZone); 937270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank localCalendar.set(2011, 2, 10, 12, 23, 34); 938270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank long localTimeMillis = localCalendar.getTimeInMillis(); 939270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank long convertedUtcTime = 940270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank CalendarUtilities.getUtcAllDayCalendarTime(localTimeMillis, localTimeZone); 941270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank // Milliseconds aren't zeroed out and may not be the same 942270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank assertEquals(convertedUtcTime/1000, correctUtcTime/1000); 943270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank 944270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank localTimeZone = TimeZone.getTimeZone("GMT+0700"); 945270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank localCalendar = new GregorianCalendar(localTimeZone); 946270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank localCalendar.set(2011, 2, 10, 12, 23, 34); 947270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank localTimeMillis = localCalendar.getTimeInMillis(); 948270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank convertedUtcTime = 949270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank CalendarUtilities.getUtcAllDayCalendarTime(localTimeMillis, localTimeZone); 950270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank assertEquals(convertedUtcTime/1000, correctUtcTime/1000); 951270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank } 952270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank 953270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank public void testGetLocalAllDayCalendarTime() { 954270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank TimeZone utcTimeZone = TimeZone.getTimeZone("UTC"); 955270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank TimeZone localTimeZone = TimeZone.getTimeZone("GMT-0700"); 956270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank GregorianCalendar correctLocal = new GregorianCalendar(localTimeZone); 957270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank correctLocal.set(2011, 2, 10, 0, 0, 0); 958270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank long correctLocalTime = correctLocal.getTimeInMillis(); 959270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank 960270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank GregorianCalendar utcCalendar = new GregorianCalendar(utcTimeZone); 961270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank utcCalendar.set(2011, 2, 10, 12, 23, 34); 962270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank long utcTimeMillis = utcCalendar.getTimeInMillis(); 963270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank long convertedLocalTime = 964270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank CalendarUtilities.getLocalAllDayCalendarTime(utcTimeMillis, localTimeZone); 965270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank // Milliseconds aren't zeroed out and may not be the same 966270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank assertEquals(convertedLocalTime/1000, correctLocalTime/1000); 967270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank 968270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank localTimeZone = TimeZone.getTimeZone("GMT+0700"); 969270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank correctLocal = new GregorianCalendar(localTimeZone); 970270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank correctLocal.set(2011, 2, 10, 0, 0, 0); 971270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank correctLocalTime = correctLocal.getTimeInMillis(); 972270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank 973270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank utcCalendar = new GregorianCalendar(utcTimeZone); 974270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank utcCalendar.set(2011, 2, 10, 12, 23, 34); 975270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank utcTimeMillis = utcCalendar.getTimeInMillis(); 976270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank convertedLocalTime = 977270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank CalendarUtilities.getLocalAllDayCalendarTime(utcTimeMillis, localTimeZone); 978270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank // Milliseconds aren't zeroed out and may not be the same 979270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank assertEquals(convertedLocalTime/1000, correctLocalTime/1000); 980270a17e49669e0bfc7bd2a6303a684a7acd1266dMarc Blank } 981393208ab154d18a876842777781ab153d34a0281Marc Blank 982393208ab154d18a876842777781ab153d34a0281Marc Blank public void testGetIntegerValueAsBoolean() { 983393208ab154d18a876842777781ab153d34a0281Marc Blank ContentValues cv = new ContentValues(); 984393208ab154d18a876842777781ab153d34a0281Marc Blank cv.put("A", 1); 985393208ab154d18a876842777781ab153d34a0281Marc Blank cv.put("B", 69); 986393208ab154d18a876842777781ab153d34a0281Marc Blank cv.put("C", 0); 987393208ab154d18a876842777781ab153d34a0281Marc Blank assertTrue(CalendarUtilities.getIntegerValueAsBoolean(cv, "A")); 988393208ab154d18a876842777781ab153d34a0281Marc Blank assertTrue(CalendarUtilities.getIntegerValueAsBoolean(cv, "B")); 989393208ab154d18a876842777781ab153d34a0281Marc Blank assertFalse(CalendarUtilities.getIntegerValueAsBoolean(cv, "C")); 990393208ab154d18a876842777781ab153d34a0281Marc Blank assertFalse(CalendarUtilities.getIntegerValueAsBoolean(cv, "D")); 991393208ab154d18a876842777781ab153d34a0281Marc Blank } 9925862a85e17e81866ca82a9905577931947fbd44eMarc Blank} 993455f8969854ec1f0ba163ae70cb02e10fb515564Marc Blank 994455f8969854ec1f0ba163ae70cb02e10fb515564Marc Blank // TODO Planned unit tests 995455f8969854ec1f0ba163ae70cb02e10fb515564Marc Blank // findNextTransition 996455f8969854ec1f0ba163ae70cb02e10fb515564Marc Blank // recurrenceFromRrule 997455f8969854ec1f0ba163ae70cb02e10fb515564Marc Blank // timeZoneToTziStringImpl 998455f8969854ec1f0ba163ae70cb02e10fb515564Marc Blank // getDSTCalendars 999455f8969854ec1f0ba163ae70cb02e10fb515564Marc Blank // millisToVCalendarTime 1000455f8969854ec1f0ba163ae70cb02e10fb515564Marc Blank // millisToEasDateTime 1001455f8969854ec1f0ba163ae70cb02e10fb515564Marc Blank // getTrueTransitionMinute 1002455f8969854ec1f0ba163ae70cb02e10fb515564Marc Blank // getTrueTransitionHour 1003455f8969854ec1f0ba163ae70cb02e10fb515564Marc Blank 1004