Home | History | Annotate | Download | only in cellular
      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 
      6 import dbus, logging
      7 from autotest_lib.client.common_lib import error
      8 
      9 sample = {
     10     'pdu' :
     11       '07914140540510F0040B916171056429F500001190804181106904D4F29C0E',
     12     'parsed' :
     13       {'text' : 'Test',
     14        'number' : '+16175046925',
     15        'timestamp' : '110908141801-04',
     16        'smsc' : '+14044550010'
     17        }
     18     }
     19 
     20 sample_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 
     40 class 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 
     95 class 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