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