1#!/usr/bin/python 2# Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import dbus, logging 7from autotest_lib.client.common_lib import error 8 9sample = { 10 'pdu' : 11 '07914140540510F0040B916171056429F500001190804181106904D4F29C0E', 12 'parsed' : 13 {'text' : 'Test', 14 'number' : '+16175046925', 15 'timestamp' : '110908141801-04', 16 'smsc' : '+14044550010' 17 } 18 } 19 20sample_multipart = { 21 'pdu' : 22 ['07912160130320F8440B916171056429F5000011909161037469A0050003920201A9' 23 'E5391DF43683E6EF7619C47EBBCF207A194F0789EB74D03D4D47BFEB7450D89D0791' 24 'D366737A5C67D3416374581E1ED3CBF23928ED1EB3EBE43219947683E8E832A85D9E' 25 'CFC3E7B20B4445A7E72077B94C9E83E86F90B80C7ADBCB72101D5D06B1CBEE331D0D' 26 'A2A3E5E539FACD2683CC6F39888E2E83D8EF71980D9ABFCDF47B585E06D1DF', 27 '07912160130320F5440B916171056429F50000119091610384691505000392020241' 28 'E437888E2E83E670769AEE02'], 29 'parsed' : 30 {'text' : 'Test of some long text but without any difficult characters' 31 ' included in the message. This needs to be over the length threshold' 32 ' for the local software to do the split.', 33 'number' : '+16175046925', 34 'timestamp' : '110919163047-04', 35 'smsc' : '+12063130028' 36 } 37 } 38 39 40class SmsStore(object): 41 '''SMS content management - this maintains an internal model of the 42 index->PDU mapping that the fakemodem program should be returning so 43 that tests can add and remove individual PDUs and handles generating 44 the correct set of responses, including the complete SMS list. 45 ''' 46 47 def __init__(self, fakemodem): 48 self.fakemodem = fakemodem 49 self.smsdict = {} 50 self.fakemodem.SetResponse('\+CMGR=', '', '+CMS ERROR: 321') 51 self.fakemodem.SetResponse('\+CMGD=', '', '+CMS ERROR: 321') 52 self._sms_regen_list() 53 54 def sms_insert(self, index, pdu): 55 '''Add a SMS to the fake modem's list.''' 56 smsc_len = int(pdu[0:1], 16) 57 mlen = len(pdu)/2 - smsc_len - 1 58 59 self.fakemodem.RemoveResponse('\+CMGD=') 60 self.fakemodem.RemoveResponse('\+CMGR=') 61 self.fakemodem.SetResponse('\+CMGD=%d' % (index), '', '') 62 self.fakemodem.SetResponse('\+CMGR=%d' % (index), 63 '+CMGR: 1,,%d\r\n%s' % (mlen, pdu), '') 64 self.fakemodem.SetResponse('\+CMGR=', '', '+CMS ERROR: 321') 65 self.fakemodem.SetResponse('\+CMGD=', '', '+CMS ERROR: 321') 66 67 self.smsdict[index] = pdu 68 self._sms_regen_list() 69 70 def sms_receive(self, index, pdu): 71 '''Add a SMS to the fake modem's list, like sms_insert(), and generate 72 an unsolicited new-sms message.''' 73 self.sms_insert(index, pdu) 74 self.fakemodem.SendUnsolicited('+CMTI: "ME",%d'%(index)) 75 76 def sms_remove(self, index): 77 '''Remove a SMS from the fake modem's list''' 78 self.fakemodem.RemoveResponse('\+CMGR=%d' % (index)) 79 self.fakemodem.RemoveResponse('\+CMGD=%d' % (index)) 80 del self.smsdict[index] 81 self._sms_regen_list() 82 83 def _sms_regen_list(self): 84 response = '' 85 keys = self.smsdict.keys() 86 keys.sort() 87 for i in keys: 88 pdu = self.smsdict[i] 89 smsc_len = int(pdu[0:1],16) 90 mlen = len(pdu)/2 - smsc_len - 1 91 response = response + '+CMGL: %d,1,,%d\r\n%s\r\n' % (i, mlen, pdu) 92 self.fakemodem.SetResponse('\+CMGL=4', response, '') 93 94 95class SmsTest(object): 96 def __init__(self, gsmsms): 97 self.gsmsms = gsmsms 98 99 def compare(self, expected, got): 100 '''Compare two SMS dictionaries, discounting the index number if 101 not specified in the first.''' 102 if expected == got: 103 return True 104 if 'index' in expected: 105 return False 106 if 'index' not in got: 107 return False 108 got = dict(got) 109 del got['index'] 110 return expected == got 111 112 def compare_list(self, expected_list, got_list): 113 if len(expected_list) != len(got_list): 114 return False 115 # There must be a more Pythonic way to do this 116 for (expected,got) in zip(expected_list, got_list): 117 if self.compare(expected, got) == False: 118 return False 119 return True 120 121 def test_get(self, index, expected): 122 try: 123 sms = self.gsmsms.Get(index) 124 except dbus.DBusException, db: 125 if expected is not None: 126 raise 127 return 128 129 if expected is None: 130 logging.info('Got %s' % sms) 131 raise error.TestFail('SMS.Get(%d) succeeded unexpectedly' % 132 index) 133 if self.compare(expected, sms) == False: 134 logging.info('Got %s, expected %s' % (sms, expected)) 135 raise error.TestFail('SMS.Get(%d) did not match expected values' % 136 index) 137 138 def test_delete(self, index, expected_success): 139 try: 140 self.gsmsms.Delete(index) 141 if expected_success == False: 142 raise error.TestFail('SMS.Delete(%d) succeeded unexpectedly' % 143 index) 144 except dbus.DBusException, db: 145 if expected_success: 146 raise 147 148 def test_list(self, expected_list): 149 sms_list = self.gsmsms.List() 150 if self.compare_list(expected_list, sms_list) == False: 151 logging.info('Got %s, expected %s' % (sms_list, expected_list)) 152 raise error.TestFail('SMS.List() did not match expected values') 153 154 def test_has_none(self): 155 '''Test that the SMS interface has no messages.''' 156 self.test_list([]) 157 self.test_get(1, None) 158 self.test_delete(1, False) 159 self.test_delete(2, False) 160 161 def test_has_one(self, parsed_sms): 162 '''Test that the SMS interface has exactly one message at index 1 163 As a side effect, deletes the message.''' 164 self.test_list([parsed_sms]) 165 self.test_get(1, parsed_sms) 166 self.test_get(2, None) 167 self.test_delete(2, False) 168 self.test_delete(1, True) 169