#!/usr/bin/env python import getopt import sys import string import re import time sys.path.insert(1,"..") from SOAPpy import SOAP import traceback DEFAULT_SERVERS_FILE = './inventory.servers' DEFAULT_METHODS = ('SimpleBuy', 'RequestForQuote','Buy','Ping') 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 -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 -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) def readServers (file): servers = [] f = open (file, 'r') while 1: line = f.readline () if line == '': break if line[0] in ('#', '\n') or line[0] in string.whitespace: continue cur = {'nonfunctional': {}} tag = None servers.append (cur) while 1: if line[0] in string.whitespace: if tag == 'nonfunctional': value = method + ' ' + cur[tag][method] else: value = cur[tag] value += ' ' + line.strip () 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 == 'nonfunctional': value = value.split (' ', 1) + [''] method = value[0] cur[tag][method] = value[1] else: cur[tag] = value line = f.readline () if line == '' or line[0] == '\n': break 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 SimpleBuy(serv, sa, epname): serv = serv._sa (sa % {'methodname':'SimpleBuy'}) return serv.SimpleBuy(ProductName="widget", Quantity = 50, Address = "this is my address") #JHawk, Phalanx require this order of params def RequestForQuote(serv, sa, epname): serv = serv._sa (sa % {'methodname':'RequestForQuote'}) return serv.RequestForQuote(Quantity=3, ProductName = "thing") # for Phalanx, JHawk def Buy(serv, sa, epname): import copy serv = serv._sa (sa % {'methodname':'Buy'}) billTo_d = {"name":"Buyer One", "address":"1 1st Street", "city":"New York", "state":"NY", "zipCode":"10000"} shipTo_d = {"name":"Buyer One ", "address":"1 1st Street ", "city":"New York ", "state":"NY ", "zipCode":"10000 "} for k,v in shipTo_d.items(): shipTo_d[k] = v[:-1] itemd1 = SOAP.structType( {"name":"widg1","quantity":200,"price":SOAP.decimalType(45.99), "_typename":"LineItem"}) itemd2 = SOAP.structType( {"name":"widg2","quantity":400,"price":SOAP.decimalType(33.45), "_typename":"LineItem"}) items_d = SOAP.arrayType( [itemd1, itemd2] ) items_d._ns = "http://www.soapinterop.org/Bid" po_d = SOAP.structType( data = {"poID":"myord","createDate":SOAP.dateTimeType(),"shipTo":shipTo_d, "billTo":billTo_d, "items":items_d}) try: # it's called PO by MST (MS SOAP Toolkit), JHawk (.NET Remoting), # Idoox WASP, Paul (SOAP::Lite), PranishK (ATL), GLUE, Aumsoft, # HP, EasySoap, and Jake (Frontier). [Actzero accepts either] return serv.Buy(PO=po_d) except: # called PurchaseOrder by KeithBa return serv.Buy(PurchaseOrder=po_d) def Ping(serv, sa, epname): serv = serv._sa (sa % {'methodname':'Ping'}) return serv.Ping() def main(): servers = DEFAULT_SERVERS_FILE methodnums = None output = 'f' invert = 0 succeed = 0 printtrace = 0 stats = 1 total = 0 fail = 0 failok = 0 notimp = 0 try: opts,args = getopt.getopt (sys.argv[1:], '?dm:io:s:t', ['help', 'method', 'debug', 'invert', 'output', 'servers=']) for opt, arg in opts: if opt in ('-?', '--help'): usage () elif opt in ('-d', '--debug'): SOAP.Config.debug = 1 elif opt in ('-i', '--invert'): invert = 1 elif opt in ('-m', '--method'): if arg == '?': methodUsage () methodnums = str2list (arg) elif opt in ('-o', '--output'): output = arg elif opt in ('-s', '--servers'): servers = arg 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 serv = SOAP.SOAPProxy(s['endpoint'], namespace = 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) try: fn = globals ()[name] except KeyboardInterrupt: raise except: if 'n' in output: print title, "test not yet implemented" notimp += 1 continue try: res = fn (serv, s['soapaction'], s['name']) if s['nonfunctional'].has_key (name): print title, "succeeded despite marked nonfunctional" elif 's' in output: print title, "succeeded " succeed += 1 except KeyboardInterrupt: print "fail" raise except: 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, sys.exc_info()[1] failok += 1 else: if 'f' in output: print title, "failed -", str (sys.exc_info()[1]) fail += 1 if stats: print " Tests ended at:", time.ctime (time.time()) 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__": main()