1#!/usr/bin/python
2
3#
4# Copyright (C) 2011 The Android Open Source Project
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#      http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19
20import logging
21import logging.handlers
22import optparse
23import sys
24import syslog
25import time
26
27import dbus
28import flimflam
29
30options = None
31
32
33def SetupSyslog():
34    syslog_handler = logging.handlers.SysLogHandler(address='/dev/log')
35    formatter = logging.Formatter('%(pathname)s: %(message)s')
36    syslog_handler.setFormatter(formatter)
37    syslog_handler.setLevel(syslog.LOG_WARNING)
38    logging.getLogger().addHandler(syslog_handler)
39    logging.getLogger().addHandler(logging.StreamHandler())
40
41
42def GetService(service_name):
43    flim = flimflam.FlimFlam(dbus.SystemBus())
44    service = flim.FindElementByNameSubstring('Service', service_name)
45    if not service:
46        logging.error('Could not find service %s' % service_name)
47        sys.exit(1)
48    return (flim, service)
49
50
51def Cycle(service_name, iteration):
52    try:
53        (flim, service) = GetService(service_name)
54
55        (connect_success, _) = flim.ConnectService(service=service,
56                                                   retry=False,
57                                                   assoc_timeout=30)
58        time.sleep(options.sleep_after_connect)
59
60        (disconnect_state, _) = flim.DisconnectService(service)
61        time.sleep(options.sleep_after_disconnect)
62
63        disconnect_success = (disconnect_state == 'idle')
64        to_return = connect_success and disconnect_success
65
66        if not to_return:
67            logging.error('Failure at iteration %d: Connect:%-6s   '
68                          'Disconnect:%-6s' %
69                          (iteration, connect_success, disconnect_success))
70        return to_return
71
72    except dbus.exceptions.DBusException, e:
73        logging.error('Unexpected DBus exception: %s' % e)
74        return False
75
76
77def main():
78    SetupSyslog()
79
80    parser = optparse.OptionParser(usage='usage: %prog [options] service-name')
81    parser.set_defaults(keep_going=False)
82
83    parser.add_option('--continue', action='store_true', dest='keep_going',
84                      help='continue after an error')
85
86    parser.add_option('--sleep_after_connect', default=0.5, type='float',
87                      help='Time (in seconds) to sleep after connect')
88
89    parser.add_option('--sleep_after_disconnect', default=0, type='float',
90                      help='Time (in seconds) to sleep after connect')
91
92    parser.add_option('--limit', default=0, type='int',
93                      help='Number of iterations to run (0 for infinite)')
94
95
96    global options
97    (options, remaining) = parser.parse_args()
98
99    if len(remaining) < 1:
100        parser.error('Must supply a service name')
101
102    (service_name, ) = remaining
103
104    (flim, service) = GetService(service_name)
105    flim.DisconnectService(service)
106
107    total = 0
108    success = 0
109    while options.limit == 0 or total < options.limit:
110        rc = Cycle(service_name, total)
111        total += 1
112        if rc:
113            success += 1
114
115        message = (
116            'Fail rate %1.3f   Pass %-5d  Fail %-5d   Total %-5d' %
117            (float(total - success) / total, success, total - success, total))
118
119        if (total % 10) == 0:
120            # Not really a warning, but we want to get this into syslog
121            logging.warning(message)
122        else:
123            print message
124
125        if not rc:
126            if options.keep_going:
127                # Don't want to run in a tight loop for a persistent failure
128                sleep_time = 10
129                logging.warning('Sleeping %d seconds' % sleep_time)
130                time.sleep(sleep_time)
131            else:
132                logging.error('Exiting on failure')
133                sys.exit(1)
134    print 'connect-disconnect: Success'
135
136
137if __name__ == '__main__':
138    try:
139        main()
140    except KeyboardInterrupt:
141        sys.exit(1)
142