|
- #!/usr/bin/env python
-
- # Copyright (c) 2001 actzero, inc. All rights reserved.
-
- # This set of clients validates when run against the servers in
- # silab.servers.
-
- import copy
- import fileinput
- import getopt
- import re
- import string
- import sys
- import time
- import traceback
-
- sys.path.insert (1, '..')
-
- from SOAPpy import SOAP
-
- SOAP.Config.typesNamespace = SOAP.NS.XSD3
- SOAP.Config.typesNamespace = SOAP.NS.XSD3
-
- ident = '$Id: silabclient.py 98 2003-03-08 05:10:01Z warnes $'
-
- DEFAULT_SERVERS_FILE = 'silab.servers'
-
- DEFAULT_METHODS = \
- (
- 'actorShouldPass', 'actorShouldFail',
- 'echoDate', 'echoBase64',
- 'echoFloat', 'echoFloatArray',
- 'echoFloatINF', 'echoFloatNaN',
- 'echoFloatNegINF', 'echoFloatNegZero',
- 'echoInteger', 'echoIntegerArray',
- 'echoString', 'echoStringArray',
- 'echoStruct', 'echoStructArray',
- 'echoVeryLargeFloat', 'echoVerySmallFloat',
- 'echoVoid',
- 'mustUnderstandEqualsOne', 'mustUnderstandEqualsZero',
- )
-
-
- def usage (error = None):
- sys.stdout = sys.stderr
-
- if error != None:
- print error
-
- print """usage: %s [options] [server ...]
- If a long option shows an argument is mandatory, it's mandatory for the
- equivalent short option also.
-
- -?, --help display this usage
- -d, --debug turn on debugging in the SOAP library
- -e, --exit-on-failure exit on the first (unexpected) failure
- -h, --harsh turn on harsh testing:
- - look for the documented error code from
- mustUnderstand failures
- - use non-ASCII strings in the string tests
- -i, --invert test servers *not* in the list of servers given
- -m, --method=METHOD#[,METHOD#...]
- call only the given methods, specify a METHOD# of ?
- for the list of method numbers
- -n, --no-stats, --no-statistics
- don't display success and failure statistics
- -N, --no-boring-stats, --no-boring-statistics
- only display unexpected failures and unimplemented
- tests, and only if non-zero
- -o, --output=TYPE turn on output, TYPE is one or more of s(uccess),
- f(ailure), n(ot implemented), F(ailed (as expected)),
- a(ll)
- [f]
- -s, --servers=FILE use FILE as list of servers to test [%s]
- -t, --stacktrace print a stack trace on each unexpected failure
- -T, --always-stacktrace
- print a stack trace on any failure
- """ % (sys.argv[0], DEFAULT_SERVERS_FILE),
-
- sys.exit (0)
-
-
- def methodUsage ():
- sys.stdout = sys.stderr
-
- print "Methods are specified by number. Multiple methods can be " \
- "specified using a\ncomma-separated list of numbers or ranges. " \
- "For example 1,4-6,8 specifies\nmethods 1, 4, 5, 6, and 8.\n"
-
- print "The available methods are:\n"
-
- half = (len (DEFAULT_METHODS) + 1) / 2
-
- for i in range (half):
- print "%4d. %-25s" % (i + 1, DEFAULT_METHODS[i]),
- if i + half < len (DEFAULT_METHODS):
- print "%4d. %-25s" % (i + 1 + half, DEFAULT_METHODS[i + half]),
- print
-
- sys.exit (0)
-
-
- # as borrowed from jake.soapware.org for float compares.
- def nearlyeq (a, b, prec = 1e-7):
- return abs (a - b) <= abs (a) * prec
-
- def readServers (file):
- servers = []
- names = {}
- cur = None
-
- f = fileinput.input(file)
-
- for line in f:
- if line[0] == '#':
- continue
-
- if line == '' or line[0] == '\n':
- cur = None
- continue
-
- if cur == None:
- cur = {'nonfunctional': {}, '_line': f.filelineno(),
- '_file': f.filename()}
- tag = None
- servers.append (cur)
-
- if line[0] in string.whitespace:
- if tag == 'nonfunctional':
- value = method + ' ' + cur[tag][method]
- else:
- value = cur[tag]
- value += ' ' + line.strip ()
- elif line[0] == '_':
- raise ValueError, \
- "%s, line %d: can't have a tag starting with `_'" % \
- (f.filename(), f.filelineno())
- else:
- tag, value = line.split (':', 1)
-
- tag = tag.strip ().lower ()
- value = value.strip ()
-
- if value[0] == '"' and value[-1] == '"':
- value = value[1:-1]
-
- if tag == 'typed':
- if value.lower() in ('0', 'no', 'false'):
- value = 0
- elif value.lower() in ('1', 'yes', 'false'):
- value = 1
- else:
- raise ValueError, \
- "%s, line %d: unknown typed value `%s'" % \
- (f.filename(), f.filelineno(), value)
- elif tag == 'name':
- if names.has_key(value):
- old = names[value]
-
- raise ValueError, \
- "%s, line %d: already saw a server named `%s' " \
- "(on line %d of %s)" % \
- (f.filename(), f.filelineno(), value,
- old['_line'], old['_file'])
- names[value] = cur
-
- if tag == 'nonfunctional':
- value = value.split (' ', 1) + ['']
-
- method = value[0]
- cur[tag][method] = value[1]
- elif tag == 'functional':
- try:
- del cur['nonfunctional'][value]
- except:
- raise ValueError, \
- "%s, line %d: `%s' not marked nonfunctional" % \
- (f.filename(), f.filelineno(), value)
- elif tag == 'like':
- try:
- new = copy.deepcopy(names[value])
- except:
- raise ValueError, \
- "%s, line %d: don't know about a server named `%s'" % \
- (f.filename(), f.filelineno(), value)
-
- # This is so we don't lose the nonfunctional methods in new or
- # in cur
-
- new['nonfunctional'].update(cur['nonfunctional'])
- del cur['nonfunctional']
-
- new.update(cur)
-
- # This is because servers and possibly names has a reference to
- # cur, so we have to keep working with cur so changes are
- # reflected in servers and names.
-
- cur.update(new)
- else:
- cur[tag] = value
-
- return servers
-
- def str2list (s):
- l = {}
-
- for i in s.split (','):
- if i.find ('-') != -1:
- i = i.split ('-')
- for i in range (int (i[0]),int (i[1]) + 1):
- l[i] = 1
- else:
- l[int (i)] = 1
-
- l = l.keys ()
- l.sort ()
-
- return l
-
- def testActorShouldPass (server, action, harsh):
- test = 42
- server = server._sa (action % {'methodname': 'echoInteger'})
- hd = SOAP.headerType ()
- hd.InteropTestHeader = SOAP.stringType ("This shouldn't fault because "
- "the mustUnderstand attribute is 0")
- hd.InteropTestHeader._setMustUnderstand (0)
- hd.InteropTestHeader._setActor (
- 'http://schemas.xmlsoap.org/soap/actor/next')
- server = server._hd (hd)
-
- result = server.echoInteger (inputInteger = test)
-
- if not SOAP.Config.typed:
- result = int (result)
-
- if result != test:
- raise Exception, "expected %s, got %s" % (test, result)
-
- def testActorShouldFail (server, action, harsh):
- test = 42
- server = server._sa (action % {'methodname': 'echoInteger'})
- hd = SOAP.headerType ()
- hd.InteropTestHeader = SOAP.stringType ("This should fault because "
- "the mustUnderstand attribute is 1")
- hd.InteropTestHeader._setMustUnderstand (1)
- hd.InteropTestHeader._setActor (
- 'http://schemas.xmlsoap.org/soap/actor/next')
- server = server._hd (hd)
-
- try:
- result = server.echoInteger (inputInteger = test)
- except SOAP.faultType, e:
- if harsh and e.faultcode != 'SOAP-ENV:MustUnderstand':
- raise AttributeError, "unexpected faultcode %s" % e.faultcode
- return
-
- raise Exception, "should fail, succeeded with %s" % result
-
- def testEchoFloat (server, action, harsh):
- server = server._sa (action % {'methodname': 'echoFloat'})
-
- for test in (0.0, 1.0, -1.0, 3853.33333333):
- result = server.echoFloat (inputFloat = test)
-
- if not SOAP.Config.typed:
- result = float (result)
-
- if not nearlyeq (result, test):
- raise Exception, "expected %.8f, got %.8f" % (test, result)
-
- def testEchoFloatArray (server, action, harsh):
- test = [0.0, 1.0, -1.0, 3853.33333333]
- server = server._sa (action % {'methodname': 'echoFloatArray'})
- result = server.echoFloatArray (inputFloatArray = test)
-
- for i in range (len (test)):
- if not SOAP.Config.typed:
- result[i] = float (result[i])
-
- if not nearlyeq (result[i], test[i]):
- raise Exception, "@ %d expected %s, got %s" % \
- (i, repr (test), repr (result))
-
- def testEchoFloatINF (server, action, harsh):
- try:
- test = float ('INF')
- except:
- test = float (1e300**2)
- server = server._sa (action % {'methodname': 'echoFloat'})
- result = server.echoFloat (inputFloat = test)
-
- if not SOAP.Config.typed:
- result = float (result)
-
- if result != test:
- raise Exception, "expected %.8f, got %.8f" % (test, result)
-
- def testEchoFloatNaN (server, action, harsh):
- try:
- test = float ('NaN')
- except:
- test = float (0.0)
- server = server._sa (action % {'methodname': 'echoFloat'})
- result = server.echoFloat (inputFloat = test)
-
- if not SOAP.Config.typed:
- result = float (result)
-
- if result != test:
- raise Exception, "expected %.8f, got %.8f" % (test, result)
-
- def testEchoFloatNegINF (server, action, harsh):
- try:
- test = float ('-INF')
- except:
- test = float (-1e300**2)
-
- server = server._sa (action % {'methodname': 'echoFloat'})
- result = server.echoFloat (inputFloat = test)
-
- if not SOAP.Config.typed:
- result = float (result)
-
- if result != test:
- raise Exception, "expected %.8f, got %.8f" % (test, result)
-
- def testEchoFloatNegZero (server, action, harsh):
- test = float ('-0.0')
- server = server._sa (action % {'methodname': 'echoFloat'})
- result = server.echoFloat (inputFloat = test)
-
- if not SOAP.Config.typed:
- result = float (result)
-
- if result != test:
- raise Exception, "expected %.8f, got %.8f" % (test, result)
-
- def testEchoInteger (server, action, harsh):
- server = server._sa (action % {'methodname': 'echoInteger'})
-
- for test in (0, 1, -1, 3853):
- result = server.echoInteger (inputInteger = test)
-
- if not SOAP.Config.typed:
- result = int (result)
-
- if result != test:
- raise Exception, "expected %.8f, got %.8f" % (test, result)
-
- def testEchoIntegerArray (server, action, harsh):
- test = [0, 1, -1, 3853]
- server = server._sa (action % {'methodname': 'echoIntegerArray'})
- result = server.echoIntegerArray (inputIntegerArray = test)
-
- for i in range (len (test)):
- if not SOAP.Config.typed:
- result[i] = int (result[i])
-
- if result[i] != test[i]:
- raise Exception, "@ %d expected %s, got %s" % \
- (i, repr (test), repr (result))
-
- relaxedStringTests = ['', 'Hello', '\'<&>"',]
- relaxedStringTests = ['Hello', '\'<&>"',]
- harshStringTests = ['', 'Hello', '\'<&>"',
- u'\u0041', u'\u00a2', u'\u0141', u'\u2342',
- u'\'<\u0041&>"', u'\'<\u00a2&>"', u'\'<\u0141&>"', u'\'<\u2342&>"',]
-
- def testEchoString (server, action, harsh):
- if harsh:
- test = harshStringTests
- else:
- test = relaxedStringTests
- server = server._sa (action % {'methodname': 'echoString'})
-
- for test in test:
- result = server.echoString (inputString = test)
-
- if result != test:
- raise Exception, "expected %s, got %s" % \
- (repr (test), repr (result))
-
- def testEchoStringArray (server, action, harsh):
- if harsh:
- test = harshStringTests
- else:
- test = relaxedStringTests
- server = server._sa (action % {'methodname': 'echoStringArray'})
- result = server.echoStringArray (inputStringArray = test)
-
- if result != test:
- raise Exception, "expected %s, got %s" % (repr (test), repr (result))
-
- def testEchoStruct (server, action, harsh):
- test = {'varFloat': 2.256, 'varInt': 474, 'varString': 'Utah'}
- server = server._sa (action % {'methodname': 'echoStruct'})
- result = server.echoStruct (inputStruct = test)
-
- if not SOAP.Config.typed:
- result.varFloat = float (result.varFloat)
- result.varInt = int (result.varInt)
-
- if not nearlyeq (test['varFloat'], result.varFloat):
- raise Exception, ".varFloat expected %s, got %s" % \
- (i, repr (test['varFloat']), repr (result.varFloat))
-
- for i in test.keys ():
- if i == 'varFloat':
- continue
-
- if test[i] != getattr (result, i):
- raise Exception, ".%s expected %s, got %s" % \
- (i, repr (test[i]), repr (getattr (result, i)))
-
-
- def testEchoStructArray (server, action, harsh):
- test = [{'varFloat': -5.398, 'varInt': -546, 'varString': 'West Virginia'},
- {'varFloat': -9.351, 'varInt': -641, 'varString': 'New Mexico'},
- {'varFloat': 1.495, 'varInt': -819, 'varString': 'Missouri'}]
- server = server._sa (action % {'methodname': 'echoStructArray'})
- result = server.echoStructArray (inputStructArray = test)
-
- for s in range (len (test)):
- if not SOAP.Config.typed:
- result[s].varFloat = float (result[s].varFloat)
- result[s].varInt = int (result[s].varInt)
-
- if not nearlyeq (test[s]['varFloat'], result[s].varFloat):
- raise Exception, \
- "@ %d.varFloat expected %s, got %s" % \
- (s, repr (test[s]['varFloat']), repr (result[s].varFloat))
-
- for i in test[s].keys ():
- if i == 'varFloat':
- continue
-
- if test[s][i] != getattr (result[s], i):
- raise Exception, "@ %d.%s expected %s, got %s" % \
- (s, i, repr (test[s][i]), repr (getattr (result[s], i)))
-
- def testEchoVeryLargeFloat (server, action, harsh):
- test = 2.2535e29
- server = server._sa (action % {'methodname': 'echoFloat'})
- result = server.echoFloat (inputFloat = test)
-
- if not SOAP.Config.typed:
- result = float (result)
-
- if not nearlyeq (result, test):
- raise Exception, "expected %s, got %s" % (repr (test), repr (result))
-
- def testEchoVerySmallFloat (server, action, harsh):
- test = 2.2535e29
- server = server._sa (action % {'methodname': 'echoFloat'})
- result = server.echoFloat (inputFloat = test)
-
- if not SOAP.Config.typed:
- result = float (result)
-
- if not nearlyeq (result, test):
- raise Exception, "expected %s, got %s" % (repr (test), repr (result))
-
- def testEchoVoid (server, action, harsh):
- server = server._sa (action % {'methodname': 'echoVoid'})
- result = server.echoVoid ()
-
- for k in result.__dict__.keys ():
- if k[0] != '_':
- raise Exception, "expected an empty structType, got %s" % \
- repr (result.__dict__)
-
- def testMustUnderstandEqualsOne (server, action, harsh):
- test = 42
- server = server._sa (action % {'methodname': 'echoInteger'})
- hd = SOAP.headerType ()
- hd.MustUnderstandThis = SOAP.stringType ("This should fault because "
- "the mustUnderstand attribute is 1")
- hd.MustUnderstandThis._setMustUnderstand (1)
- server = server._hd (hd)
-
- try:
- result = server.echoInteger (inputInteger = test)
- except SOAP.faultType, e:
- if harsh and e.faultcode != 'SOAP-ENV:MustUnderstand':
- raise AttributeError, "unexpected faultcode %s" % e.faultcode
- return
-
- raise Exception, "should fail, succeeded with %s" % result
-
- def testMustUnderstandEqualsZero (server, action, harsh):
- test = 42
- server = server._sa (action % {'methodname': 'echoInteger'})
- hd = SOAP.headerType ()
- hd.MustUnderstandThis = SOAP.stringType ("This shouldn't fault because "
- "the mustUnderstand attribute is 0")
- hd.MustUnderstandThis._setMustUnderstand (0)
- server = server._hd (hd)
-
- result = server.echoInteger (inputInteger = test)
-
- if not SOAP.Config.typed:
- result = int (result)
-
- if result != test:
- raise Exception, "expected %s, got %s" % (test, result)
-
- def testEchoDate (server, action, harsh):
- test = time.gmtime (time.time ())
- server = server._sa (action % {'methodname': 'echoDate'})
- if SOAP.Config.namespaceStyle == '1999':
- result = server.echoDate (inputDate = SOAP.timeInstantType (test))
- else:
- result = server.echoDate (inputDate = SOAP.dateTimeType (test))
-
- if not SOAP.Config.typed and type (result) in (type (''), type (u'')):
- p = SOAP.SOAPParser()
- result = p.convertDateTime(result, 'timeInstant')
-
- if result != test[:6]:
- raise Exception, "expected %s, got %s" % (repr (test), repr (result))
-
- def testEchoBase64 (server, action, harsh):
- test = '\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\xa0\xb0\xc0\xd0\xe0\xf0'
- server = server._sa (action % {'methodname': 'echoBase64'})
- result = server.echoBase64 (inputBase64 = SOAP.base64Type (test))
-
- if not SOAP.Config.typed:
- import base64
- result = base64.decodestring(result)
-
- if result != test:
- raise Exception, "expected %s, got %s" % (repr (test), repr (result))
-
-
- def main ():
- stats = 1
- total = 0
- fail = 0
- failok = 0
- succeed = 0
- exitonfailure = 0
- harsh = 0
- invert = 0
- printtrace = 0
- methodnums = None
- notimp = 0
- output = 'f'
- servers = DEFAULT_SERVERS_FILE
-
- started = time.time ()
-
- try:
- opts, args = getopt.getopt (sys.argv[1:], '?dehim:nNo:s:tT',
- ['help', 'debug', 'exit-on-failure', 'harsh', 'invert',
- 'method', 'no-stats', 'no-statistics',
- 'no-boring-statistics', 'no-boring-stats', 'output',
- 'servers=', 'stacktrace', 'always-stacktrace'])
-
- for opt, arg in opts:
- if opt in ('-?', '--help'):
- usage ()
- elif opt in ('-d', '--debug'):
- SOAP.Config.debug = 1
- elif opt in ('-h', '--harsh'):
- harsh = 1
- elif opt in ('-i', '--invert'):
- invert = 1
- elif opt in ('-e', '--exit-on-failure'):
- exitonfailure = 1
- elif opt in ('-m', '--method'):
- if arg == '?':
- methodUsage ()
- methodnums = str2list (arg)
- elif opt in ('-n', '--no-stats', '--no-statistics'):
- stats = 0
- elif opt in ('-N', '--no-boring-stats', '--no-boring-statistics'):
- stats = -1
- elif opt in ('-o', '--output'):
- output = arg
- elif opt in ('-s', '--servers'):
- servers = arg
- elif opt in ('-t', '--stacktrace'):
- printtrace = 1
- elif opt in ('-T', '--always-stacktrace'):
- printtrace = 2
- else:
- raise AttributeError, \
- "Recognized but unimplemented option `%s'" % opt
- except SystemExit:
- raise
- except:
- usage (sys.exc_info ()[1])
-
- if 'a' in output:
- output = 'fFns'
-
- servers = readServers (servers)
-
- if methodnums == None:
- methodnums = range (1, len (DEFAULT_METHODS) + 1)
-
- limitre = re.compile ('|'.join (args), re.IGNORECASE)
-
- for s in servers:
- if (not not limitre.match (s['name'])) == invert:
- continue
-
- try: typed = s['typed']
- except: typed = 1
-
- try: style = s['style']
- except: style = 1999
-
- SOAP.Config.typed = typed
- SOAP.Config.namespaceStyle = style
-
- server = SOAP.SOAPProxy (s['endpoint'], ("m", s['namespace']))
-
- for num in (methodnums):
- if num > len (DEFAULT_METHODS):
- break
-
- total += 1
-
- name = DEFAULT_METHODS[num - 1]
-
- title = '%s: %s (#%d)' % (s['name'], name, num)
-
- if SOAP.Config.debug:
- print "%s:" % title
-
- try:
- fn = globals ()['test' + name[0].upper () + name[1:]]
- except KeyboardInterrupt:
- raise
- except:
- if 'n' in output:
- print title, "test not yet implemented"
- notimp += 1
- continue
-
- try:
- fn (server, s['soapaction'], harsh)
- if s['nonfunctional'].has_key (name):
- print title, \
- "succeeded despite being marked nonfunctional"
- if 's' in output:
- print title, "succeeded"
- succeed += 1
- except KeyboardInterrupt:
- raise
- except:
- fault = str (sys.exc_info ()[1])
- if fault[-1] == '\n':
- fault = fault[:-1]
-
- if s['nonfunctional'].has_key (name):
- if 'F' in output:
- t = 'as expected'
- if s['nonfunctional'][name] != '':
- t += ', ' + s['nonfunctional'][name]
- print title, "failed (%s) -" % t, fault
- if printtrace > 1:
- traceback.print_exc ()
- failok += 1
- else:
- if 'f' in output:
- print title, "failed -", fault
- if printtrace:
- traceback.print_exc ()
- fail += 1
-
- if exitonfailure:
- return -1
-
- if stats:
- print " Tests started at:", time.ctime (started)
- if stats > 0:
- print " Total tests: %d" % total
- print " Successes: %d (%3.2f%%)" % \
- (succeed, 100.0 * succeed / total)
- if stats > 0 or fail > 0:
- print "Failed unexpectedly: %d (%3.2f%%)" % \
- (fail, 100.0 * fail / total)
- if stats > 0:
- print " Failed as expected: %d (%3.2f%%)" % \
- (failok, 100.0 * failok / total)
- if stats > 0 or notimp > 0:
- print " Not implemented: %d (%3.2f%%)" % \
- (notimp, 100.0 * notimp / total)
-
- return fail + notimp
-
- if __name__ == '__main__':
- try:
- sys.exit (main ())
- except KeyboardInterrupt:
- sys.exit (0)
|