diff options
author | Benoit Foucher <benoit@zeroc.com> | 2016-11-25 13:13:22 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2016-11-25 13:13:22 +0100 |
commit | dcdc32af1fced49d80a8ccd93230e15d91ab45d8 (patch) | |
tree | eb69e2555fbd54496fce8a33f4dd610e1473ff51 /scripts | |
parent | C# IceSSL/configuration log expired certificate exceptions. (diff) | |
download | ice-dcdc32af1fced49d80a8ccd93230e15d91ab45d8.tar.bz2 ice-dcdc32af1fced49d80a8ccd93230e15d91ab45d8.tar.xz ice-dcdc32af1fced49d80a8ccd93230e15d91ab45d8.zip |
Refactored test scripts
Diffstat (limited to 'scripts')
51 files changed, 4222 insertions, 3344 deletions
diff --git a/scripts/Controller.ice b/scripts/Controller.ice new file mode 100644 index 00000000000..24ee0b97e29 --- /dev/null +++ b/scripts/Controller.ice @@ -0,0 +1,86 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +module Test +{ + +module Common +{ + +exception ServerFailedException +{ + string reason; +}; + +interface Server +{ + void waitTestSuccess(); + void waitForServer() throws ServerFailedException; + void terminate(); +}; + +class Config +{ + optional(1) string protocol; + optional(2) bool mx; + optional(3) bool serialize; + optional(4) bool compress; + optional(5) bool ipv6; +}; + +sequence<bool> BoolSeq; +sequence<string> StringSeq; + +class OptionOverrides +{ + optional(1) StringSeq protocol; + optional(2) BoolSeq mx; + optional(3) BoolSeq serialize; + optional(4) BoolSeq compress; + optional(5) BoolSeq ipv6; +}; + +exception TestCaseNotExistException +{ + string reason; +}; + +exception TestCaseFailedException +{ + string output; +}; + +interface TestCase +{ + string startServerSide(Config config) + throws TestCaseFailedException; + + string stopServerSide(bool success) + throws TestCaseFailedException; + + string runClientSide(string host, Config config) + throws TestCaseFailedException; + + void destroy(); +}; + +interface Controller +{ + Server* runServer(string lang, string testsuite, string protocol, string host, bool winrt, string testcase, + StringSeq options); + + TestCase* runTestCase(string lang, string testsuite, string testcase) + throws TestCaseNotExistException; + + OptionOverrides getOptionOverrides(); +}; + +}; + +}; diff --git a/scripts/Controller.py b/scripts/Controller.py new file mode 100755 index 00000000000..d89175eb244 --- /dev/null +++ b/scripts/Controller.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import os, sys +from Util import * + +class ControllerDriver(Driver): + + class Current(Driver.Current): + + def __init__(self, driver, testsuite, testcase, protocol, host, args): + Driver.Current.__init__(self, driver, testsuite, Result(testsuite, driver.debug)) + self.testcase = testcase + self.host = host + self.args = args + self.config.protocol = protocol + + @classmethod + def getOptions(self): + return ("", ["clean", "id=", "endpoints=", "interface="]) + + @classmethod + def usage(self): + print("") + print("Controller driver options:") + print("--id=<identity> The identify of the controller object.") + print("--endpoints=<endpts> The endpoints to listen on.") + print("--interface=<IP> The interface to use to discover the controller.") + print("--clean Remove trust settings (OS X).") + + def __init__(self, options, *args, **kargs): + Driver.__init__(self, options, *args, **kargs) + self.id = "controller" + self.endpoints = "tcp" + self.interface = "" + self.clean = False + parseOptions(self, options, { "clean" : "clean" }) + + def run(self, mappings): + + if isinstance(platform, Darwin): + # + # On OS X, we set the trust settings on the certificate to prevent + # the Web browsers from prompting the user about the unstrusted + # certificate. Some browsers such as Chrome don't provide the + # option to set this trust settings. + # + serverCert = os.path.join(toplevel, "certs", "server.pem") + if self.clean: + if os.system("security verify-cert -c " + serverCert + " >& /dev/null") == 0: + sys.stdout.write("removing trust settings for the HTTP server certificate... ") + sys.stdout.flush() + if os.system("security remove-trusted-cert " + serverCert) != 0: + print("\nerror: couldn't remove trust settings for the HTTP server certificate") + else: + print("ok") + else: + print("trust settings already removed") + return + else: + if os.system("security verify-cert -c " + serverCert + " >& /dev/null") != 0: + sys.stdout.write("adding trust settings for the HTTP server certificate... ") + sys.stdout.flush() + if os.system("security add-trusted-cert -r trustAsRoot " + serverCert) != 0: + print("error: couldn't add trust settings for the HTTP server certificate") + print("ok") + print("run " + sys.argv[0] + " --clean to remove the trust setting") + + import Ice + Ice.loadSlice(os.path.join(toplevel, "scripts", "Controller.ice")) + import Test + + class ServerI(Test.Common.Server): + def __init__(self, driver, current): + self.driver = driver + self.current = current + + def waitForServer(self, c): + if not self.current: + raise Test.Common.ServerFailedException("couldn't find test suite") + + try: + self.current.testcase.getServerTestCase()._startServerSide(self.current) + except Exception as ex: + raise Test.Common.ServerFailedException(str(ex)) + + def waitTestSuccess(self, c): + c.adapter.remove(c.id) + if self.current: + self.current.testcase.getServerTestCase()._stopServerSide(self.current, True) + + def terminate(self, c): + c.adapter.remove(c.id) + if self.current: + self.current.testcase.getServerTestCase()._stopServerSide(self.current, False) + + class TestCaseI(Test.Common.TestCase): + def __init__(self, driver, current): + self.driver = driver + self.current = current + self.serverSideRunning = False + + def startServerSide(self, config, c): + self.updateCurrent(config) + + # Depending on the configuration, either use an IPv4, IPv6 or BT address for Ice.Default.Host + if self.current.config.ipv6: + if not self.driver.hostIPv6: + raise Test.Common.TestCaseFailedException("no IPv6 address set with --host-ipv6") + self.current.host = self.driver.hostIPv6 + elif self.current.config.protocol == "bt": + if not self.driver.hostBT: + raise Test.Common.TestCaseFailedException("no Bluetooth address set with --host-bt") + self.current.host = self.driver.hostBT + else: + self.current.host = self.driver.host if self.driver.host else self.driver.interface + + try: + self.current.testcase.getServerTestCase()._startServerSide(self.current) + self.serverSideRunning = True + return self.current.host + except Exception as ex: + raise Test.Common.TestCaseFailedException(self.current.result.getOutput() + "\n" + str(ex)) + + def stopServerSide(self, success, c): + if self.serverSideRunning: + try: + self.current.testcase.getServerTestCase()._stopServerSide(self.current, success) + return self.current.result.getOutput() + except Exception as ex: + raise Test.Common.TestCaseFailedException(self.current.result.getOutput() + "\n" + str(ex)) + + def runClientSide(self, host, config, c): + self.updateCurrent(config) + if host: + current.host = host + try: + self.current.testcase.getClientTestCase()._runClientSide(self.current) + return self.current.result.getOutput() + except Exception as ex: + raise Test.Common.TestCaseFailedException(self.current.result.getOutput() + "\n" + str(ex)) + + def destroy(self, c): + if self.serverSideRunning: + try: + self.current.testcase.getServerTestCase()._stopServerSide(self.current, False) + except: + pass + c.adapter.remove(c.id) + + def updateCurrent(self, config): + attrs = ["protocol", "mx", "serialize", "compress", "ipv6"] + for a in attrs: + v = getattr(config, a) + if v is not Ice.Unset: + setattr(self.current.config, a, v) + + class ControllerI(Test.Common.Controller): + def __init__(self, driver): + self.driver = driver + self.server = None + self.testcase = None + + def runServer(self, mapping, testsuite, protocol, host, winrt, testcase, args, c): + self.terminate() + try: + current = self.driver.getCurrent(mapping, testsuite, testcase, protocol, host, args) + except Test.Common.TestCaseNotExistException: + current = None + self.server = Test.Common.ServerPrx.uncheckedCast(c.adapter.addWithUUID(ServerI(self.driver, current))) + return self.server + + def runTestCase(self, mapping, testsuite, testcase, c): + self.terminate() + current = self.driver.getCurrent(mapping, testsuite, testcase) + self.testcase = Test.Common.TestCasePrx.uncheckedCast(c.adapter.addWithUUID(TestCaseI(self.driver, current))) + return self.testcase + + def getOptionOverrides(self, c): + return Test.Common.OptionOverrides(ipv6=([False] if not self.driver.hostIPv6 else [False, True])) + + def terminate(self): + if self.server: + try: + self.server.terminate() + except: + pass + self.server = None + + if self.testcase: + try: + self.testcase.destroy() + except: + pass + self.testcase = None + + initData = Ice.InitializationData() + initData.properties = Ice.createProperties(); + initData.properties.setProperty("Ice.Plugin.IceSSL", "IceSSL:createIceSSL") + initData.properties.setProperty("IceSSL.DefaultDir", os.path.join(toplevel, "certs")) + initData.properties.setProperty("IceSSL.CertFile", "server.p12") + initData.properties.setProperty("IceSSL.Password", "password") + initData.properties.setProperty("IceSSL.Keychain", "test.keychain") + initData.properties.setProperty("IceSSL.KeychainPassword", "password") + initData.properties.setProperty("IceSSL.VerifyPeer", "0"); + initData.properties.setProperty("Ice.ThreadPool.Server.SizeMax", "10") + initData.properties.setProperty("Ice.Plugin.IceDiscovery", "IceDiscovery:createIceDiscovery") + initData.properties.setProperty("IceDiscovery.DomainId", "TestController") + if self.interface: + initData.properties.setProperty("IceDiscovery.Interface", self.interface) + initData.properties.setProperty("Ice.Default.Host", self.interface) + #initData.properties.setProperty("Ice.Trace.Network", "3") + #initData.properties.setProperty("Ice.Trace.Protocol", "1") + initData.properties.setProperty("ControllerAdapter.Endpoints", self.endpoints) + initData.properties.setProperty("ControllerAdapter.AdapterId", Ice.generateUUID()) + + communicator = Ice.initialize(initData) + try: + adapter = communicator.createObjectAdapter("ControllerAdapter") + adapter.add(ControllerI(self), communicator.stringToIdentity(self.id)) + adapter.activate() + communicator.waitForShutdown() + finally: + communicator.destroy() + + def getCurrent(self, mapping, testsuite, testcase, protocol=None, host=None, args=[]): + import Test + mapping = Mapping.getByName(mapping) + if not mapping: + raise Test.Common.TestCaseNotExistException("unknown mapping {0}".format(mapping)) + + ts = mapping.findTestSuite(testsuite) + if not ts: + raise Test.Common.TestCaseNotExistException("unknown testsuite {0}".format(testsuite)) + + tc = ts.findTestCase("server" if ts.getId() == "Ice/echo" else (testcase or "client/server")) + if not tc or not tc.getServerTestCase(): + raise Test.Common.TestCaseNotExistException("unknown testcase {0}".format(testcase)) + + return ControllerDriver.Current(self, ts, tc, protocol, host, args) + + def getProps(self, process, current): + props = Driver.getProps(self, process, current) + if isinstance(process, IceProcess) and current.host: + props["Ice.Default.Host"] = current.host + return props + + def getArgs(self, process, current): + return current.args + + def isWorkerThread(self): + return True + +Driver.add("controller", ControllerDriver, default=True) + +runTests()
\ No newline at end of file diff --git a/scripts/Expect.py b/scripts/Expect.py index 1e63e99978d..0140a881d28 100755 --- a/scripts/Expect.py +++ b/scripts/Expect.py @@ -479,7 +479,7 @@ class Expect (object): raises a TIMEOUT exception. If timeout is None, the wait is indefinite. - The exit status is returned. A negative exit status means + The exit tus is returned. A negative exit status means the application was killed by a signal. """ if self.p is None: @@ -493,6 +493,10 @@ class Expect (object): time.sleep(0.1) if self.p and self.p.poll() is None: raise TIMEOUT ('timedwait exceeded timeout') + elif win32: + # We poll on Windows or othewise KeyboardInterrupt isn't delivered + while self.p.poll() is None: + time.sleep(0.5) if self.p is None: return self.exitstatus @@ -503,7 +507,8 @@ class Expect (object): if win32 and self.exitstatus != 0 and self.killed is not None: self.exitstatus = -self.killed global processes - del processes[self.p.pid] + if self.p.pid in processes: + del processes[self.p.pid] self.p = None self.r.join() # Simulate a match on EOF @@ -519,6 +524,10 @@ class Expect (object): # First try to break the app. Don't bother if this is win32 # and we're using java. It won't break (BREAK causes a stack # trace). + + if self.p is None: + return + if self.hasInterruptSupport(): try: if win32: @@ -633,6 +642,32 @@ class Expect (object): def trace(self, suppress = None): self.r.enabletrace(suppress) + def waitSuccess(self, exitstatus = 0, timeout = None): + """Wait for the process to terminate for up to timeout seconds, and + validate the exit status is as expected.""" + + def test(result, expected): + if expected != result: + raise RuntimeError("unexpected exit status: expected: %d, got %d\n" % (expected, result)) + + self.wait(timeout) + if self.mapping == "java": + if self.killed is not None: + if win32: + test(self.exitstatus, -self.killed) + else: + if self.killed == signal.SIGINT: + test(130, self.exitstatus) + else: + test(self.exitstatus, exitstatus) + else: + test(self.exitstatus, exitstatus) + else: + test(self.exitstatus, exitstatus) + + def getOutput(self): + return self.buf + def hasInterruptSupport(self): """Return True if the application gracefully terminated, False otherwise.""" if win32 and self.mapping == "java": diff --git a/scripts/Glacier2Util.py b/scripts/Glacier2Util.py new file mode 100644 index 00000000000..81bdc050f67 --- /dev/null +++ b/scripts/Glacier2Util.py @@ -0,0 +1,76 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os +from Util import * + +class Glacier2Router(ProcessFromBinDir, Server): + + def __init__(self, portnum=10, passwords={"userid": "abc123"}, *args, **kargs): + Server.__init__(self, "glacier2router", mapping=Mapping.getByName("cpp"), desc="Glacier2 router", + readyCount=2, *args, **kargs) + self.portnum = portnum + self.passwords = passwords + + def setup(self, current): + if self.passwords: + path = os.path.join(current.testcase.getPath(), "passwords") + with open(path, "w") as file: + command = "%s %s" % (sys.executable, + os.path.abspath(os.path.join(toplevel, "scripts", "icehashpassword.py"))) + + # + # For Linux ARM default rounds makes test slower (Usually runs on embbeded boards) + # + if current.config.buildPlatform.find("arm") >= 0: + command += " --rounds 100000" + + for user, password in self.passwords.items(): + p = subprocess.Popen(command, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + stdin=subprocess.PIPE) + p.stdin.write(password.encode('UTF-8')) + p.stdin.write('\r\n'.encode('UTF-8')) + p.stdin.flush() + if(p.wait() != 0): + raise RuntimeError("icehashpassword.py failed:\n" + p.stdout.read().decode('UTF-8').strip()) + file.write("%s %s\n" % (user, p.stdout.readline().decode('UTF-8').strip())) + current.testcase.files.append(path) + + def getProps(self, current): + props = Server.getProps(self, current) + props.update({ + "Glacier2.Client.Endpoints" : current.getTestEndpoint(self.portnum), + "Glacier2.Server.Endpoints" : "tcp", + "Ice.Admin.Endpoints" : current.getTestEndpoint(self.portnum + 1, "tcp"), + "Ice.Admin.InstanceName" : "Glacier2", + }) + if self.passwords: + props["Glacier2.CryptPasswords"] = os.path.join("{testdir}", "passwords") + if isinstance(current.testcase.getTestSuite(), Glacier2TestSuite): + # Add the properties provided by the Glacier2TestSuite routerProps parameter. + props.update(current.testcase.getTestSuite().getRouterProps(self, current)) + return props + + def getClientProxy(self, current): + return "Glacier2/router:{0}".format(current.getTestEndpoint(self.portnum)) + +class Glacier2TestSuite(TestSuite): + + def __init__(self, path, routerProps={}, testcases=None, *args, **kargs): + if testcases is None: + testcases = [ClientServerTestCase(servers=[Glacier2Router(), Server()])] + TestSuite.__init__(self, path, testcases, *args, **kargs) + self.routerProps = routerProps + + def getRouterProps(self, process, current): + return self.routerProps(process, current) if callable(self.routerProps) else self.routerProps.copy() + diff --git a/scripts/IceBoxUtil.py b/scripts/IceBoxUtil.py new file mode 100644 index 00000000000..e7a9b71d021 --- /dev/null +++ b/scripts/IceBoxUtil.py @@ -0,0 +1,27 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os +from Util import * + +class IceBox(ProcessFromBinDir, Server): + + processType = "icebox" + +class IceBoxAdmin(ProcessFromBinDir, Client): + + processType = "iceboxadmin" + + def getMapping(self, current): + # IceBox admin is only provided with the C++/Java, not C# + mapping = self.mapping or current.testcase.getMapping() + if isinstance(mapping, CppMapping) or isinstance(mapping, JavaMapping): + return mapping + else: + return Mapping.getByName("cpp") diff --git a/scripts/IceGridAdmin.py b/scripts/IceGridAdmin.py deleted file mode 100644 index f020d088865..00000000000 --- a/scripts/IceGridAdmin.py +++ /dev/null @@ -1,329 +0,0 @@ -#!/usr/bin/env python -# ********************************************************************** -# -# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. -# -# This copy of Ice is licensed to you under the terms described in the -# ICE_LICENSE file included in this distribution. -# -# ********************************************************************** - -import sys, os, TestUtil, shlex -from threading import Thread - -# -# Set nreplicas to a number N to test replication with N replicas. -# -nreplicas=0 -#nreplicas=1 - -iceGridPort = 12010; - -nodeOptions = r' --Ice.Warn.Connections=0' + \ - r' --IceGrid.InstanceName=TestIceGrid' + \ - r' --IceGrid.Node.Endpoints=default' + \ - r' --IceGrid.Node.WaitTime=240' + \ - r' --Ice.ProgramName=icegridnode' + \ - r' --IceGrid.Node.Trace.Replica=0' + \ - r' --IceGrid.Node.Trace.Activator=0' + \ - r' --IceGrid.Node.Trace.Adapter=0' + \ - r' --IceGrid.Node.Trace.Server=0' + \ - r' --IceGrid.Node.ThreadPool.SizeWarn=0' + \ - r' --IceGrid.Node.PrintServersReady=node1' + \ - r' --Ice.NullHandleAbort' + \ - r' --Ice.ThreadPool.Server.Size=1' + \ - r' --Ice.ServerIdleTime=0' - -registryOptions = r' --Ice.Warn.Connections=0' + \ - r' --IceGrid.InstanceName=TestIceGrid' + \ - r' --IceGrid.Registry.PermissionsVerifier=TestIceGrid/NullPermissionsVerifier' + \ - r' --IceGrid.Registry.AdminPermissionsVerifier=TestIceGrid/NullPermissionsVerifier' + \ - r' --IceGrid.Registry.SSLPermissionsVerifier=TestIceGrid/NullSSLPermissionsVerifier' + \ - r' --IceGrid.Registry.AdminSSLPermissionsVerifier=TestIceGrid/NullSSLPermissionsVerifier' + \ - r' --IceGrid.Registry.Server.Endpoints=default' + \ - r' --IceGrid.Registry.Internal.Endpoints=default' + \ - r' --IceGrid.Registry.SessionManager.Endpoints=default' + \ - r' --IceGrid.Registry.AdminSessionManager.Endpoints=default' + \ - r' --IceGrid.Registry.Trace.Session=0' + \ - r' --IceGrid.Registry.Trace.Application=0' + \ - r' --IceGrid.Registry.Trace.Node=0' + \ - r' --IceGrid.Registry.Trace.Replica=0' + \ - r' --IceGrid.Registry.Trace.Adapter=0' + \ - r' --IceGrid.Registry.Trace.Object=0' + \ - r' --IceGrid.Registry.Trace.Server=0' + \ - r' --IceGrid.Registry.Trace.Locator=0' + \ - r' --IceGrid.Registry.SessionTimeout=60' + \ - r' --Ice.ThreadPool.Server.Size=1 ' + \ - r' --Ice.ThreadPool.Client.SizeWarn=0' + \ - r' --IceGrid.Registry.Client.ThreadPool.SizeWarn=0' + \ - r' --Ice.ServerIdleTime=0' + \ - r' --IceGrid.Registry.DefaultTemplates="' + \ - os.path.abspath(os.path.join(TestUtil.toplevel, "cpp", "config", "templates.xml") + '"') - -if TestUtil.ipv6 and TestUtil.isDarwin(): - registryOptions += r' --IceGrid.Registry.Discovery.Interface="::1"' - -def getDefaultLocatorProperty(): - - i = 0 - property = '--Ice.Default.Locator="TestIceGrid/Locator'; - objrefs = "" - while i < nreplicas + 1: - objrefs = objrefs + ':default -p ' + str(iceGridPort + i) - i = i + 1 - - return ' %s%s"' % (property, objrefs) - -def startIceGridRegistry(testdir, dynamicRegistration = False): - - iceGrid = TestUtil.getIceGridRegistry() - - command = ' --nowarn ' + registryOptions - if dynamicRegistration: - command += r' --IceGrid.Registry.DynamicRegistration' - - procs = [] - i = 0 - while i < (nreplicas + 1): - - if i == 0: - name = "registry" - else: - name = "replica-" + str(i) - - dataDir = os.path.join(testdir, "db", name) - if not os.path.exists(dataDir): - os.mkdir(dataDir) - else: - cleanDbDir(dataDir) - - sys.stdout.write("starting icegrid " + name + "... ") - sys.stdout.flush() - cmd = command + ' ' + \ - r' --Ice.ProgramName=' + name + \ - r' --IceGrid.Registry.Client.Endpoints="default -p ' + str(iceGridPort + i) + '" ' + \ - r' --IceGrid.Registry.LMDB.MapSize=1 --IceGrid.Registry.LMDB.Path="' + dataDir + '" ' - - if i > 0: - cmd += r' --IceGrid.Registry.ReplicaName=' + name + ' ' + getDefaultLocatorProperty() - - driverConfig = TestUtil.DriverConfig("server") - driverConfig.lang = "cpp" - proc = TestUtil.startServer(iceGrid, cmd, driverConfig, count = 5) - procs.append(proc) - print("ok") - - i = i + 1 - return procs - -def shutdownIceGridRegistry(procs): - - i = nreplicas - while i > 0: - sys.stdout.write("shutting down icegrid replica-" + str(i) + "... ") - sys.stdout.flush() - iceGridAdmin("registry shutdown replica-" + str(i)) - print("ok") - i = i - 1 - - sys.stdout.write("shutting down icegrid registry... ") - sys.stdout.flush() - iceGridAdmin("registry shutdown") - print("ok") - - for p in procs: - p.waitTestSuccess() - -def iceGridNodePropertiesOverride(): - - # - # Create property overrides from command line options. - # - overrideOptions = '' - for opt in shlex.split(TestUtil.getCommandLineProperties("", TestUtil.DriverConfig("server"), "")): - opt = opt.strip().replace("--", "") - index = opt.find("=") - if index == -1: - overrideOptions += ("%s=1 ") % opt - else: - key = opt[0:index] - value = opt[index + 1:] - if(value.find(' ') == -1): - overrideOptions += ("%s=%s ") % (key, value) - else: - # - # NOTE: We need 2 backslash before the quote to run the - # C# test/IceGrid/simple test with SSL. - # - overrideOptions += ("%s=\\\"%s\\\" ") % (key, value.replace('"', '\\\\\\"')) - - return overrideOptions - -def startIceGridNode(testdir): - - iceGrid = TestUtil.getIceGridNode() - dataDir = os.path.join(testdir, "db", "node") - if not os.path.exists(dataDir): - os.mkdir(dataDir) - else: - cleanDbDir(dataDir) - - overrideOptions = '" ' + iceGridNodePropertiesOverride() - overrideOptions += ' Ice.ServerIdleTime=0 Ice.PrintProcessId=0 Ice.PrintAdapterReady=0"' - - sys.stdout.write("starting icegrid node... ") - sys.stdout.flush() - command = r' --nowarn ' + nodeOptions + getDefaultLocatorProperty() + \ - r' --IceGrid.Node.Data="' + dataDir + '"' \ - r' --IceGrid.Node.Name=localnode' + \ - r' --IceGrid.Node.PropertiesOverride=' + overrideOptions - - driverConfig = TestUtil.DriverConfig("server") - driverConfig.lang = "cpp" - proc = TestUtil.startServer(iceGrid, command, driverConfig, adapter='node1') - - print("ok") - - return proc - -def iceGridAdmin(cmd, ignoreFailure = False): - - iceGridAdmin = TestUtil.getIceGridAdmin() - - user = r"admin1" - if cmd == "registry shutdown": - user = r"shutdown" - command = getDefaultLocatorProperty() + r" --IceGridAdmin.Username=" + user + " --IceGridAdmin.Password=test1 " + \ - r' -e "' + cmd + '"' - - if TestUtil.appverifier: - TestUtil.setAppVerifierSettings([TestUtil.getIceGridAdmin()]) - - driverConfig = TestUtil.DriverConfig("client") - driverConfig.lang = "cpp" - proc = TestUtil.startClient(iceGridAdmin, command, driverConfig) - status = proc.wait() - - if TestUtil.appverifier: - TestUtil.appVerifierAfterTestEnd([TestUtil.getIceGridAdmin()]) - - if not ignoreFailure and status: - print(proc.buf) - sys.exit(1) - return proc.buf - -def killNodeServers(): - - for server in iceGridAdmin("server list"): - server = server.strip() - iceGridAdmin("server disable " + server, True) - iceGridAdmin("server signal " + server + " SIGKILL", True) - -def iceGridTest(application, additionalOptions = "", applicationOptions = ""): - - testdir = os.getcwd() - if not TestUtil.isWin32() and os.getuid() == 0: - print - print("*** can't run test as root ***") - print - return - - client = TestUtil.getDefaultClientFile() - if TestUtil.getDefaultMapping() != "java" and TestUtil.getDefaultMapping() != "java-compat": - client = os.path.join(testdir, client) - - clientOptions = ' ' + getDefaultLocatorProperty() + ' ' + additionalOptions - - targets = [] - if TestUtil.appverifier: - targets = [client, TestUtil.getIceGridNode(), TestUtil.getIceGridRegistry()] - TestUtil.setAppVerifierSettings(targets) - - registryProcs = startIceGridRegistry(testdir) - iceGridNodeProc = startIceGridNode(testdir) - - javaHome = os.environ.get("JAVA_HOME", None) - javaExe = os.path.join(javaHome, "bin", "java") if javaHome else "java" - - if application != "": - sys.stdout.write("adding application... ") - sys.stdout.flush() - iceGridAdmin("application add -n '" + os.path.join(testdir, application) + "' " + - "test.dir='" + testdir + "' " + - "ice.bindir='" + TestUtil.getCppBinDir() + "' " + - "java.exe='" + javaExe + "' " + - applicationOptions) - print("ok") - - sys.stdout.write("starting client... ") - sys.stdout.flush() - clientProc = TestUtil.startClient(client, clientOptions, TestUtil.DriverConfig("client"), startReader = False) - print("ok") - clientProc.startReader() - clientProc.waitTestSuccess() - - if application != "": - sys.stdout.write("remove application... ") - sys.stdout.flush() - iceGridAdmin("application remove Test") - print("ok") - - sys.stdout.write("shutting down icegrid node... ") - sys.stdout.flush() - iceGridAdmin("node shutdown localnode") - print("ok") - shutdownIceGridRegistry(registryProcs) - iceGridNodeProc.waitTestSuccess() - - if TestUtil.appverifier: - TestUtil.appVerifierAfterTestEnd(targets) - -def iceGridClientServerTest(additionalClientOptions, additionalServerOptions): - - testdir = os.getcwd() - server = TestUtil.getDefaultServerFile() - client = TestUtil.getDefaultClientFile() - if TestUtil.getDefaultMapping() != "java" and TestUtil.getDefaultMapping() != "java-compat": - server = os.path.join(testdir, server) - client = os.path.join(testdir, client) - - targets = [] - if TestUtil.appverifier: - targets = [client, server, TestUtil.getIceGridRegistry()] - TestUtil.setAppVerifierSettings(targets) - - clientOptions = getDefaultLocatorProperty() + ' ' + additionalClientOptions - serverOptions = getDefaultLocatorProperty() + ' ' + additionalServerOptions - - registryProcs = startIceGridRegistry(testdir, True) - - sys.stdout.write("starting server... ") - sys.stdout.flush() - serverProc= TestUtil.startServer(server, serverOptions, TestUtil.DriverConfig("server")) - print("ok") - - sys.stdout.write("starting client... ") - sys.stdout.flush() - clientProc = TestUtil.startClient(client, clientOptions, TestUtil.DriverConfig("client")) - print("ok") - - clientProc.waitTestSuccess() - serverProc.waitTestSuccess() - - shutdownIceGridRegistry(registryProcs) - - if TestUtil.appverifier: - TestUtil.appVerifierAfterTestEnd(targets) - -def cleanDbDir(path): - for filename in [ os.path.join(path, f) for f in os.listdir(path) if f != ".gitignore"]: - if os.path.isdir(filename): - cleanDbDir(filename) - try: - os.rmdir(filename) - except OSError: - # This might fail if the directory is empty (because - # it itself contains a .gitignore file. - pass - else: - os.remove(filename) diff --git a/scripts/IceGridUtil.py b/scripts/IceGridUtil.py new file mode 100644 index 00000000000..9eb6157cb9a --- /dev/null +++ b/scripts/IceGridUtil.py @@ -0,0 +1,265 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os +from Util import * + +class IceGridProcess: + + def __init__(self, replica): + self.replica = replica + + def getProps(self, current): + props = self.getParentProps(current) + testcase = current.testcase + while testcase and not isinstance(testcase, IceGridTestCase): testcase = testcase.parent + if self.replica is None: + props["Ice.Default.Locator"] = testcase.getMasterLocator(current) + else: + for r in testcase.icegridregistry: + # Match either the IceGridRegistrySlave object or the slave replica number + if self.replica in [r, r.name]: + props["Ice.Default.Locator"] = r.getLocator(current) + break + return props + +class IceGridServer(IceGridProcess, Server): + + def __init__(self, replica=None, *args, **kargs): + Server.__init__(self, *args, **kargs) + IceGridProcess.__init__(self, replica) + + getParentProps = Server.getProps # Used by IceGridProcess to get the server properties + +class IceGridClient(IceGridProcess, Client): + + def __init__(self, replica=None, *args, **kargs): + Client.__init__(self, *args, **kargs) + IceGridProcess.__init__(self, replica) + + getParentProps = Client.getProps # Used by IceGridProcess to get the client properties + +class IceGridAdmin(ProcessFromBinDir, IceGridClient): + + def __init__(self, replica=None, username="admin1", password="test1", *args, **kargs): + IceGridClient.__init__(self, replica=replica, exe="icegridadmin", mapping=Mapping.getByName("cpp"), + *args, **kargs) + self.username = username + self.password = password + + def getProps(self, current): + props = IceGridClient.getProps(self, current) + props["IceGridAdmin.Username"] = self.username + props["IceGridAdmin.Password"] = self.password + return props + +class IceGridNode(ProcessFromBinDir, Server): + + def __init__(self, name="localnode", *args, **kargs): + + Server.__init__(self, "icegridnode", mapping=Mapping.getByName("cpp"), desc="IceGrid node " + name, + ready="node", *args, **kargs) + self.name = name + + def setup(self, current): + # Create the database directory + os.mkdir(os.path.join(current.testcase.getPath(), "node-{0}".format(self.name))) + + def teardown(self, current, success): + # Remove the database directory tree + try: + shutil.rmtree(os.path.join(current.testcase.getPath(), "node-{0}".format(self.name))) + except: + pass + + def getProps(self, current): + props = { + 'IceGrid.InstanceName' : 'TestIceGrid', + 'IceGrid.Node.Endpoints' : 'default', + 'IceGrid.Node.WaitTime' : 240, + 'Ice.ProgramName' : 'icegridnode', + 'IceGrid.Node.Trace.Replica' : 0, + 'IceGrid.Node.Trace.Activator' : 0, + 'IceGrid.Node.Trace.Adapter' : 0, + 'IceGrid.Node.Trace.Server' : 0, + 'IceGrid.Node.ThreadPool.SizeWarn' : 0, + 'IceGrid.Node.PrintServersReady' : 'node', + 'IceGrid.Node.Name' : self.name, + 'IceGrid.Node.Data' : '{testdir}/node-{process.name}', + 'IceGrid.Node.PropertiesOverride' : self.getPropertiesOverride(current), + 'Ice.Default.Locator' : current.testcase.getLocator(current), + 'Ice.NullHandleAbort' : 1, + } + return props + + def getEnv(self, current): + # Add environment variable for servers based on the test case mapping. + return Server().getEffectiveEnv(current) + + def getPropertiesOverride(self, current): + # Add properties for servers based on the test case mapping. + props = Server().getEffectiveProps(current, {}) + return ' '.join(["{0}={1}".format(k, val(v, escapeQuotes=True)) for k, v in props.items()]) + + def shutdown(self, current): + current.testcase.runadmin(current, "node shutdown {0}".format(self.name)) + +class IceGridRegistry(ProcessFromBinDir, Server): + + def __init__(self, name, portnum=20, readyCount=5, *args, **kargs): + Server.__init__(self, "icegridregistry", mapping=Mapping.getByName("cpp"), desc="IceGrid registry " + name, + readyCount=readyCount, *args, **kargs) + self.portnum = portnum + self.name = name + + def setup(self, current): + # Create the database directory + os.mkdir(os.path.join(current.testcase.getPath(), "registry-{0}".format(self.name))) + + def teardown(self, current, success): + # Remove the database directory tree + try: + shutil.rmtree(os.path.join(current.testcase.getPath(), "registry-{0}".format(self.name))) + except: + pass + + def getProps(self, current): + props = { + 'IceGrid.InstanceName' : 'TestIceGrid', + 'IceGrid.Registry.PermissionsVerifier' : 'TestIceGrid/NullPermissionsVerifier', + 'IceGrid.Registry.AdminPermissionsVerifier' : 'TestIceGrid/NullPermissionsVerifier', + 'IceGrid.Registry.SSLPermissionsVerifier' : 'TestIceGrid/NullSSLPermissionsVerifier', + 'IceGrid.Registry.AdminSSLPermissionsVerifier' : 'TestIceGrid/NullSSLPermissionsVerifier', + 'IceGrid.Registry.Server.Endpoints' : 'default', + 'IceGrid.Registry.Internal.Endpoints' : 'default', + 'IceGrid.Registry.Client.Endpoints' : self.getEndpoints(current), + 'IceGrid.Registry.Discovery.Interface' : '"::1"' if current.config.ipv6 and isinstance(platform, Darwin) else '', + 'IceGrid.Registry.Discovery.Port' : current.driver.getTestPort(99), + 'IceGrid.Registry.SessionManager.Endpoints' : 'default', + 'IceGrid.Registry.AdminSessionManager.Endpoints' : 'default', + 'IceGrid.Registry.SessionTimeout' : 60, + 'IceGrid.Registry.ReplicaName' : self.name, + 'Ice.ProgramName' : self.name, + 'Ice.PrintAdapterReady' : 1, + 'Ice.Warn.Connections' : 0, + 'Ice.ThreadPool.Client.SizeWarn' : 0, + 'IceGrid.Registry.LMDB.MapSize' : 1, + 'IceGrid.Registry.LMDB.Path' : '{testdir}/registry-{process.name}', + 'IceGrid.Registry.Client.ThreadPool.SizeWarn' : 0, + 'IceGrid.Registry.DefaultTemplates' : + '"' + os.path.abspath(os.path.join(toplevel, "cpp", "config", "templates.xml")) + '"' + } + return props + + def getEndpoints(self, current): + return current.getTestEndpoint(self.portnum) + + def getLocator(self, current): + return "TestIceGrid/Locator:{0}".format(self.getEndpoints(current)) + + def shutdown(self, current): + current.testcase.runadmin(current, "registry shutdown {0}".format(self.name), replica=self.name) + +class IceGridRegistryMaster(IceGridRegistry): + + def __init__(self, portnum=20, *args, **kargs): + IceGridRegistry.__init__(self, "Master", portnum, *args, **kargs) + +class IceGridRegistrySlave(IceGridRegistry): + + def __init__(self, replica=1, portnum=None, *args, **kargs): + IceGridRegistry.__init__(self, "Slave{0}".format(replica), (20 + replica) if portnum is None else portnum, + *args, **kargs) + + def getProps(self, current): + props = IceGridRegistry.getProps(self, current) + props["Ice.Default.Locator"] = current.testcase.getMasterLocator(current) + return props + +class IceGridTestCase(TestCase): + + def __init__(self, name="IceGrid", icegridregistry=None, icegridnode=None, application="application.xml", + variables={}, targets=[], exevars={}, *args, **kargs): + TestCase.__init__(self, name, *args, **kargs) + if icegridnode: + self.icegridnode = icegridnode if isinstance(icegridnode, list) else [icegridnode] + else: + self.icegridnode = [IceGridNode()] + + if icegridregistry: + self.icegridregistry = icegridregistry if isinstance(icegridregistry, list) else [icegridregistry] + else: + self.icegridregistry = [IceGridRegistryMaster(), IceGridRegistrySlave(1)] + + self.application = application + self.variables = variables + self.targets = targets + + # Variables for built executables + self.exevars = { "server.dir" : "server" } + self.exevars.update(exevars) + + def init(self, mapping, testsuite): + TestCase.init(self, mapping, testsuite) + + # + # Add IceGrid servers at the begining of the server list, IceGrid needs to be + # started first! + # + self.servers = self.icegridregistry + self.icegridnode + self.servers + + def setupClientSide(self, current): + if self.application: + javaHome = os.environ.get("JAVA_HOME", None) + serverProps = Server().getProps(current) + variables = { + "test.dir" : self.getPath(), + "ice.bindir" : self.mapping.getBinDir(current), + "java.exe" : os.path.join(javaHome, "bin", "java") if javaHome else "java", + "icebox.exe" : IceBox().getCommandLine(current), + "icegridnode.exe" : IceGridNode().getCommandLine(current), + "icegridregistry.exe" : IceGridRegistryMaster().getCommandLine(current), + "properties-override" : self.icegridnode[0].getPropertiesOverride(current) + } + + # Add variables that point to the directories containing the built executables + for (k, v) in self.exevars.items(): + variables[k] = current.getBuildDir(v) + + variables.update(self.variables) + varStr = " ".join(["{0}={1}".format(k, val(v, True)) for k,v in variables.items()]) + targets = " ".join(self.targets) + self.runadmin(current, "application add -n {0} {1} {2}".format(self.application, varStr, targets)) + + def teardownClientSide(self, current, success): + if self.application: + self.runadmin(current, "application remove Test") + + for p in self.icegridnode + self.icegridregistry: + p.shutdown(current) + + def getLocator(self, current): + endpoints = ":".join([s.getEndpoints(current) for s in self.servers if isinstance(s, IceGridRegistry)]) + return "TestIceGrid/Locator:{0}".format(endpoints) + + def getMasterLocator(self, current): + for s in self.servers: + if isinstance(s, IceGridRegistryMaster): + return "TestIceGrid/Locator:{0}".format(s.getEndpoints(current)) + + def runadmin(self, current, cmd, replica="Master", exitstatus=0, quiet=False): + admin = IceGridAdmin(args=["-r", replica, "-e", cmd], replica=replica, quiet=quiet) + admin.run(current, exitstatus=exitstatus) + return admin.getOutput() + + def runWithDriver(self, current): + current.driver.runClientServerTestCase(current) + + def getClientType(self): + return "client" diff --git a/scripts/IcePatch2Util.py b/scripts/IcePatch2Util.py new file mode 100644 index 00000000000..1a7fda7ca83 --- /dev/null +++ b/scripts/IcePatch2Util.py @@ -0,0 +1,15 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +from Util import * + +class IcePatch2Calc(ProcessFromBinDir, Process): + + def __init__(self, *args, **kargs): + Process.__init__(self, exe="icepatch2calc", mapping=Mapping.getByName("cpp"), *args, **kargs) diff --git a/scripts/IceStormUtil.py b/scripts/IceStormUtil.py index a619fe5809c..7aeb5ddd775 100644 --- a/scripts/IceStormUtil.py +++ b/scripts/IceStormUtil.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # ********************************************************************** # # Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. @@ -9,254 +7,223 @@ # # ********************************************************************** -import os, sys -import TestUtil +import sys, os +from Util import * -global testdir -global toplevel +class IceStorm(ProcessFromBinDir, Server): -origIceBoxService = ' --Ice.Admin.Endpoints="default -p {0}"' + \ - ' --Ice.Admin.InstanceName=IceBox{0}' + \ - ' --Ice.Default.Locator=' + def __init__(self, instanceName="IceStorm", replica=0, nreplicas=0, transient=False, portnum=0, *args, **kargs): + Server.__init__(self, exe="icebox", ready="IceStorm", mapping=Mapping.getByName("cpp"), *args, **kargs) + self.portnum = portnum + self.replica = replica + self.nreplicas = nreplicas + self.transient = transient + self.instanceName = instanceName + self.desc = self.instanceName if self.nreplicas == 0 else "{0} replica #{1}".format(self.instanceName, + self.replica) + + def setup(self, current): + # Create the database directory + os.mkdir(os.path.join(current.testcase.getPath(), "{0}-{1}.db".format(self.instanceName, self.replica))) + + def teardown(self, current, success): + # Remove the database directory tree + try: + shutil.rmtree(os.path.join(current.testcase.getPath(), "{0}-{1}.db".format(self.instanceName, self.replica))) + except: + pass + + def getProps(self, current): + props = Server.getProps(self, current) + + # Default properties + props.update({ + 'IceBox.Service.IceStorm' : 'IceStormService,' + getIceSoVersion() + ':createIceStorm', + 'IceBox.PrintServicesReady' : 'IceStorm', + 'IceBox.InheritProperties' : 1, + 'IceStorm.InstanceName' : self.instanceName, + 'Ice.Admin.InstanceName' : 'IceBox', + 'Ice.Warn.Dispatch' : 0, + 'Ice.Warn.Connections' : 0, + 'IceStorm.LMDB.MapSize' : 1, + 'IceStorm.LMDB.Path' : '{testdir}/{process.instanceName}-{process.replica}.db', + }) + + if self.nreplicas > 0: + props['IceStorm.NodeId'] = self.replica -origIceBoxEndpoints = ' --IceBoxAdmin.ServiceManager.Proxy="IceBox{0}/admin -f IceBox.ServiceManager: default -p {0}"' + if self.transient: + props["IceStorm.Transient"] = 1 + + # + # Add endpoint properties here as these properties depend on the worker thread running the + # the test case for the port number. The port number is computed by the driver based on a + # fixed portnum index for each IceStorm endpoint (portnum = 0 for the topic manager endpoint, + # portnum=1 for the publish endpoint, portnum=2 for the node endpoint and portnum=3 for the + # icebox admin endpoint). + # + + # Manager, publish, node and admin ndpoints for given replica number + manager = lambda replica: current.getTestEndpoint(self.portnum + replica * 4 + 0) + publish = lambda replica: "{0}:{1}".format(current.getTestEndpoint(self.portnum + replica * 4 + 1), + current.getTestEndpoint(self.portnum + replica * 4 + 1, "udp")) + node = lambda replica: current.getTestEndpoint(self.portnum + replica * 4 + 2) + admin = lambda replica: current.getTestEndpoint(self.portnum + replica * 4 + 3) + + # The endpoints for the given replica + props.update({ + "IceStorm.TopicManager.Endpoints" : manager(self.replica), + "IceStorm.Publish.Endpoints" : publish(self.replica), + "Ice.Admin.Endpoints" : admin(self.replica), + }) + + # Compute the node and replicated endpoints to be configured for each replica + if self.nreplicas > 0: + props['IceStorm.Node.Endpoints'] = node(self.replica) + for i in range(0, self.nreplicas): + props["IceStorm.Nodes.{0}".format(i)] = "{2}/node{0}:{1}".format(i, node(i), self.instanceName) + props['IceStorm.ReplicatedTopicManagerEndpoints'] = ":".join([manager(i) for i in range(0, self.nreplicas)]) + props['IceStorm.ReplicatedPublishEndpoints'] = ":".join([publish(i) for i in range(0, self.nreplicas)]) + + return props + + def getInstanceName(self): + return self.instanceName + + def getTopicManager(self, current): + # Return the endpoint for this IceStorm replica + return "{1}/TopicManager:{0}".format(current.getTestEndpoint(self.portnum + self.replica * 4), self.instanceName) + + def getReplicatedTopicManager(self, current): + # Return the replicated endpoints for IceStorm + if self.nreplicas == 0: + return self.getTopicManager(current) + manager = lambda replica: current.getTestEndpoint(self.portnum + replica * 4) + return "{1}/TopicManager:{0}".format(":".join([manager(i) for i in range(0, self.nreplicas)]), self.instanceName) + + def shutdown(self, current): + # Shutdown this replica by connecting to the IceBox service manager with iceboxadmin + endpoint = current.getTestEndpoint(self.portnum + self.replica * 4 + 3) + props = { "IceBoxAdmin.ServiceManager.Proxy" : "IceBox/admin -f IceBox.ServiceManager:" + endpoint } + IceBoxAdmin().run(current, props=props, args=['shutdown']) + +class IceStormProcess: + + def __init__(self, instanceName=None, instance=None): + self.instanceName = instanceName + self.instance = instance + + def getProps(self, current): + + # + # An IceStorm client is provided with the IceStormAdmin.TopicManager.Default property set + # to the "instance" topic manager proxy if "instance" is set. Otherwise, if a single it's + # set to the replicated topic manager if a specific "instance name" is provided or there's + # only one IceStorm instance name deployed. If IceStorm multiple instance names are set, + # the client is given an IceStormAdmin.<instance name> property for each instance containing + # the replicated topic manager proxy. + # + + props = self.getParentProps(current) + testcase = current.testcase + while testcase and not isinstance(testcase, IceStormTestCase): testcase = testcase.parent + if self.instance: + props["IceStormAdmin.TopicManager.Default"] = self.instance.getTopicManager(current) + else: + instanceNames = [self.instanceName] if self.instanceName else testcase.getInstanceNames() + if len(instanceNames) == 1: + props["IceStormAdmin.TopicManager.Default"] = testcase.getTopicManager(current, instanceNames[0]) + else: + for name in instanceNames: + props["IceStormAdmin.TopicManager.{0}".format(name)] = testcase.getTopicManager(current, name) + return props -# Turn off the dispatch and connection warnings -- they are expected -# when using a replicated IceStorm. -origIceStormService = ' --IceBox.Service.IceStorm=IceStormService,' + TestUtil.getIceSoVersion() + ':createIceStorm' + \ - ' --IceStorm.TopicManager.Endpoints="default -p %d"' + \ - ' --IceBox.PrintServicesReady=IceStorm' + \ - ' --IceBox.InheritProperties=1' + \ - ' --Ice.Warn.Dispatch=0 --Ice.Warn.Connections=0' + \ - ' --Ice.ServerIdleTime=0' +class IceStormAdmin(ProcessFromBinDir, IceStormProcess, Client): -origIceStormProxy = '%s/TopicManager:default -p %d' + def __init__(self, instanceName=None, instance=None, *args, **kargs): + Client.__init__(self, exe="icestormadmin", mapping=Mapping.getByName("cpp"), *args, **kargs) + IceStormProcess.__init__(self, instanceName, instance) -origIceStormReference = ' --IceStormAdmin.TopicManager.Default="%s"' + getParentProps = Client.getProps # Used by IceStormProcess to get the client properties -class IceStormUtil(object): - def __init__(self, toplevel, testdir): - self.toplevel = toplevel - self.testdir = testdir - self.iceBox = TestUtil.getIceBox() - self.iceBoxAdmin = os.path.join(TestUtil.getCppBinDir(), "iceboxadmin") - self.iceStormAdmin = os.path.join(TestUtil.getCppBinDir(), "icestormadmin") +class Subscriber(IceStormProcess, Server): - def runIceBoxAdmin(self, endpts, command): - proc = TestUtil.startClient(self.iceBoxAdmin, endpts + " " + command, echo = False) - proc.waitTestSuccess() - return proc.buf + processType = "subscriber" - def admin(self, cmd, **args): - self.adminWithRef(self.iceStormReference, cmd, **args) + def __init__(self, instanceName=None, instance=None, *args, **kargs): + Server.__init__(self, *args, **kargs) + IceStormProcess.__init__(self, instanceName, instance) - def adminWithRef(self, ref, cmd, expect = None): - proc = TestUtil.startClient(self.iceStormAdmin, ref + r' -e "%s"' % cmd, echo = False) - if expect: - proc.expect(expect) - proc.wait() - else: - proc.waitTestSuccess() - - def reference(self): - return self.iceStormReference - def proxy(self): - return self.iceStormProxy - -class Replicated(IceStormUtil): - def __init__(self, toplevel, testdir, - additional = None, - replicatedPublisher = True, - dbDir = "db", - instanceName="IceStorm", port = 12010): - IceStormUtil.__init__(self, toplevel, testdir) - self.procs = [] - self.nendpoints = [] # Node endpoints - self.instanceName = instanceName - self.ibendpoints = [] # IceBox endpoints - self.isendpoints = [] # TopicManager endpoints - self.ipendpoints = [] # Publisher endpoints - for replica in range(0, 3): - self.nendpoints.append(port + 100 + replica * 10) - self.ibendpoints.append(port + replica * 10) - self.isendpoints.append(port + (replica * 10)+1) - self.ipendpoints.append(port + (replica * 10)+2) - replicaProperties = "" - sep ='' - replicaTopicManagerEndpoints = '' - replicaPublishEndpoints = '' - for replica in range(0, 3): - replicaProperties = replicaProperties + \ - ' --IceStorm.Nodes.%d="%s/node%d:default -t 10000 -p %d"' % ( - replica, instanceName, replica, self.nendpoints[replica]) - replicaTopicManagerEndpoints = replicaTopicManagerEndpoints + "%sdefault -p %d" % ( - sep, self.isendpoints[replica]) - replicaPublishEndpoints = replicaPublishEndpoints + "%sdefault -p %d" % (sep, self.ipendpoints[replica]) - sep = ':' - replicaProperties = replicaProperties + \ - ' --IceStorm.NodeId=%d --IceStorm.Node.Endpoints="default -p %d"' + \ - ' --IceStorm.ReplicatedTopicManagerEndpoints="' +\ - replicaTopicManagerEndpoints + '"' - if replicatedPublisher: - replicaProperties = replicaProperties + \ - ' --IceStorm.ReplicatedPublishEndpoints="' + replicaPublishEndpoints + '"' - self.iceBoxEndpoints = [] - self.iceBoxAdminEndpoints = [] - self.iceStormEndpoints = [] - self.replicaProperties = [] - self.dbHome= [] - self.iceStormDBEnv= [] - self.procs = [] - for replica in range(0, 3): - self.iceBoxEndpoints.append(origIceBoxService.format(self.ibendpoints[replica])) - self.iceBoxAdminEndpoints.append(origIceBoxEndpoints.format(self.ibendpoints[replica])) - service = origIceStormService % self.isendpoints[replica] - service = service + ' --IceStorm.Publish.Endpoints="default -p %d:udp -p %d"' % ( - self.ipendpoints[replica], self.ipendpoints[replica]) - if instanceName: - service = service + ' --IceStorm.InstanceName=%s ' % instanceName - #service = service + ' --IceStorm.Trace.Election=1' - #service = service + ' --IceStorm.Trace.Replication=1' - #service = service + ' --IceStorm.Trace.Subscriber=1' - #service = service + ' --IceStorm.Trace.Topic=1' - #service = service + ' --Ice.Trace.Network=3' - #service = service + ' --Ice.Trace.Protocol=1' - if additional: - service = service + " " + additional - self.iceStormEndpoints.append(service) - self.replicaProperties.append(replicaProperties % (replica, self.nendpoints[replica])) - dbHome = os.path.join(self.testdir, "%d.%s" % (replica, dbDir)) - self.dbHome.append(dbHome) - TestUtil.cleanDbDir(dbHome) - - self.iceStormDBEnv.append(' --IceStorm.LMDB.MapSize=1 --IceStorm.LMDB.Path="%s"' % dbHome) - self.procs.append(None) - - topicReplicaProxy = '%s/TopicManager:%s' % (instanceName, replicaTopicManagerEndpoints) - self.iceStormProxy = topicReplicaProxy - self.iceStormReference = ' --IceStormAdmin.TopicManager.Default="%s"' % topicReplicaProxy - - def adminForReplica(self, replica, cmd, expect = None, **args): - ep = self.isendpoints[replica] - proxy = origIceStormProxy % (self.instanceName, self.isendpoints[replica]) - ref = origIceStormReference % proxy - self.adminWithRef(ref, cmd, expect, **args) - - def clean(self): - for replica in range(0, 3): - TestUtil.cleanDbDir(self.dbHome[replica]) - - def start(self, echo = True, **args): - if echo: - sys.stdout.write("starting icestorm replicas... ") - sys.stdout.flush() - # Start replicas. - for replica in range(0, 3): - if echo: - sys.stdout.write(str(replica) + " ") - sys.stdout.flush() - self.startReplica(replica, echo=False, **args) - if echo: - print("ok") - - def startReplica(self, replica, echo = True, additionalOptions = ""): - if echo: - sys.stdout.write("starting icestorm replica %d..." % replica + " ") - sys.stdout.flush() - - proc = TestUtil.startServer(self.iceBox, - self.iceBoxEndpoints[replica] + - self.iceStormEndpoints[replica] + - self.replicaProperties[replica] + - self.iceStormDBEnv[replica] + - additionalOptions, - adapter = "IceStorm", - echo = False) - self.procs[replica] = proc - if echo: - print("ok") - - def stop(self): - for replica in range(0, 3): - self.stopReplica(replica) - - def stopReplica(self, replica): - if self.procs[replica]: - self.runIceBoxAdmin(self.iceBoxAdminEndpoints[replica], "shutdown") - self.procs[replica].waitTestSuccess() - self.procs[replica] = None - - def reference(self, replica=-1): - if replica == -1: - return self.iceStormReference - ep = self.isendpoints[replica] - proxy = origIceStormProxy % (self.instanceName, self.isendpoints[replica]) - return origIceStormReference % proxy - -class NonReplicated(IceStormUtil): - def __init__(self, toplevel, testdir, transient, \ - additional = None, dbDir = "db", instanceName=None, port = 12010): - IceStormUtil.__init__(self, toplevel, testdir) - iceBoxPort = port - iceStormPort = port + 1 - publisherPort = port + 2 - self.iceBoxService = origIceBoxService.format(iceBoxPort) - self.iceBoxEndpoints = origIceBoxEndpoints.format(iceBoxPort) - self.iceStormService = origIceStormService % (iceStormPort) - self.dbDir = dbDir - - if instanceName: - self.iceStormService = self.iceStormService + ' --IceStorm.InstanceName=%s ' % instanceName - else: - instanceName = "IceStorm" + getParentProps = Server.getProps # Used by IceStormProcess to get the server properties - if publisherPort: - self.iceStormService = self.iceStormService + ' --IceStorm.Publish.Endpoints="default -p %d:udp -p %d"' % ( - publisherPort, publisherPort) - else: - self.iceStormService = self.iceStormService + ' --IceStorm.Publish.Endpoints="default:udp"' - self.transient = transient - if self.transient: - self.iceStormService = self.iceStormService + " --IceStorm.Transient=1" - if additional: - self.iceStormService = self.iceStormService + " " + additional - self.iceStormProxy = origIceStormProxy % (instanceName, iceStormPort) - self.iceStormReference = origIceStormReference % self.iceStormProxy +class Publisher(IceStormProcess, Client): - self.dbHome = os.path.join(self.testdir, self.dbDir) - TestUtil.cleanDbDir(self.dbHome) + processType = "publisher" - self.iceStormDBEnv = ' --IceStorm.LMDB.MapSize=1 --IceStorm.LMDB.Path="%s"' % self.dbHome + def __init__(self, instanceName=None, instance=None, *args, **kargs): + Client.__init__(self, *args, **kargs) + IceStormProcess.__init__(self, instanceName, instance) - def clean(self): - TestUtil.cleanDbDir(self.dbHome) + getParentProps = Client.getProps # Used by IceStormProcess to get the client properties - def start(self, echo = True, additionalOptions = ""): - if echo: - if self.transient: - sys.stdout.write("starting transient icestorm service... ") - else: - sys.stdout.write("starting icestorm service... ") - sys.stdout.flush() - - self.proc = TestUtil.startServer(self.iceBox, - self.iceBoxService + - self.iceStormService + - self.iceStormDBEnv + - additionalOptions, adapter = "IceStorm", - echo = False) - if echo: - print("ok") - return self.proc - - def stop(self): - self.runIceBoxAdmin(self.iceBoxEndpoints, "shutdown") - self.proc.waitTestSuccess() - -def init(toplevel, testdir, type, **args): - if type == "replicated": - return Replicated(toplevel, testdir, **args) - if type == "transient": - return NonReplicated(toplevel, testdir, True, **args) - return NonReplicated(toplevel, testdir, False, **args) +class IceStormTestCase(TestCase): + + def __init__(self, name, icestorm, *args, **kargs): + TestCase.__init__(self, name, *args, **kargs) + self.icestorm = icestorm if isinstance(icestorm, list) else [icestorm] + + def init(self, mapping, testsuite): + TestCase.init(self, mapping, testsuite) + + # + # Add icestorm servers at the begining of the server list, IceStorm needs to be + # started first! + # + self.servers = self.icestorm + self.servers + + def runWithDriver(self, current): + current.driver.runClientServerTestCase(current) + + def startIceStorm(self, current): + for icestorm in self.icestorm: + icestorm.start(current) + + def stopIceStorm(self, current): + self.shutdown(current) + for icestorm in self.icestorm: + icestorm.stop(current, True) + + def restartIceStorm(self, current): + self.stopIceStorm(current) + self.startIceStorm(current) + + def shutdown(self, current): + for icestorm in self.icestorm: + icestorm.shutdown(current) + + def runadmin(self, current, cmd, instanceName=None, instance=None, exitstatus=0, quiet=False): + admin = IceStormAdmin(instanceName, instance, args=["-e", cmd], quiet=quiet) + admin.run(current, exitstatus=exitstatus) + return admin.getOutput() + + def getTopicManager(self, current, instanceName=None): + if not instanceName: + # Return the topic manager proxy from the first IceStorm server + return self.icestorm[0].getReplicatedTopicManager(current) + + # + # Otherwise, search for an IceStorm server with the given instance + # name and return its replicated topic manager proxy + # + for s in self.icestorm: + if s.getInstanceName() == instanceName: + return s.getReplicatedTopicManager(current) + + def getInstanceNames(self): + # Return the different IceStorm instance names deployed with this + # test case + names = set() + for s in self.icestorm: + names.add(s.getInstanceName()) + return list(names) diff --git a/scripts/LocalDriver.py b/scripts/LocalDriver.py new file mode 100644 index 00000000000..c723444683e --- /dev/null +++ b/scripts/LocalDriver.py @@ -0,0 +1,521 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os +from Util import * + +# +# The Executor class runs testsuites on multiple worker threads. +# +class Executor: + + def __init__(self, threadlocal, workers, continueOnFailure): + self.threadlocal = threadlocal + self.workers = workers - 1 + self.queue = [] + self.mainThreadQueue = [] + self.queueLength = 0 + self.failure = False + self.continueOnFailure = continueOnFailure + self.lock = threading.Lock() + + def submit(self, testsuite): + if testsuite.isMainThreadOnly() or self.workers == 0: + self.mainThreadQueue.append(testsuite) + else: + self.queue.append(testsuite) + self.queueLength += 1 + + def get(self, total, mainThread=False): + with self.lock: + if self.failure: + return None + queue = self.mainThreadQueue if mainThread else self.queue + if len(queue) == 0: + return None + self.queueLength -= 1 + return (queue.pop(0), total - self.queueLength) + + def runTestSuites(self, driver, total, results, mainThread=False): + while True: + item = self.get(total, mainThread) + if not item: + results.put(None) # Notify the main thread that there are not more tests to run + break + + (testsuite, index) = item + result = Result(testsuite, not driver.isWorkerThread()) + current = LocalDriver.Current(driver, testsuite, result, index, total) + try: + testsuite.run(current) + except KeyboardInterrupt: + raise + except: + print(traceback.format_exc()) + pass + results.put((result, mainThread)) + if not result.isSuccess() and not self.continueOnFailure: + with self.lock: self.failure = True + + def runUntilCompleted(self, driver, start): + if self.queueLength == 0: + return [] + + total = self.queueLength + if self.workers == 0 and start > 0: + for i in range(1, start): + if len(self.mainThreadQueue) == 0: + break + self.mainThreadQueue.pop(0) + self.queueLength -= 1 + + # + # Worker threads dequeue and run testsuites. They push resuts to the results + # queue. The thread stops when there are no more testsuite to dequeue. + # + resultList = [] + results = queue.Queue() + def worker(num): + self.threadlocal.num = num + try: + self.runTestSuites(driver, total, results) + except Exception as ex: + print("unexpected exception raised from worker thread:\n" + str(ex)) + results.put(None) # Notify the main thread that we're done + + # + # Start the worker threads + # + threads=[] + for i in range(min(self.workers, total)): + t = threading.Thread(target=worker, args=[i]) + t.start() + threads.append(t) + + try: + # + # Run the main thread testsuites. + # + self.runTestSuites(driver, total, results, True) + + # + # Dequeue results and print out the testuite output for each test. + # + count = len(threads) + 1 + while count > 0: + try: + r = results.get(timeout=1) + if not r: + count -= 1 + continue + except queue.Empty: + continue + + (result, mainThread) = r + resultList.append(result) + if not mainThread: + sys.stdout.write(result.getOutput()) + except KeyboardInterrupt: + with self.lock: + self.failure = True + if threads: + print("Terminating (waiting for worker threads to terminate)...") + raise + finally: + # + # Wait for worker threads to be done. + # + for t in threads: + t.join() + + # + # Print out remaining testsuites. + # + try: + while True: + r = results.get_nowait() + if r: + (result, mainThread) = r + resultList.append(result) + if not mainThread: + sys.stdout.write(result.getOutput()) + except queue.Empty: + pass + + return resultList + +# +# Runner to run the test cases locally. +# +class TestCaseRunner: + + def filterOptions(self, options): + return options + + def startServerSide(self, testcase, current): + testcase._startServerSide(current) + + def stopServerSide(self, testcase, current, success): + testcase._stopServerSide(current, success) + + def runClientSide(self, testcase, current): + testcase._runClientSide(current) + + def destroy(self): + pass + +# +# Runner to run the test cases remotely with the controller (requires IcePy) +# +class RemoteTestCaseRunner(TestCaseRunner): + + def __init__(self, clientPrx, serverPrx, interface): + import Ice + Ice.loadSlice(os.path.join(toplevel, "scripts", "Controller.ice")) + import Test + + initData = Ice.InitializationData() + initData.properties = Ice.createProperties() + initData.properties.setProperty("Ice.Plugin.IceDiscovery", "IceDiscovery:createIceDiscovery") + initData.properties.setProperty("IceDiscovery.DomainId", "TestController") + if interface: + initData.properties.setProperty("IceDiscovery.Interface", interface) + initData.properties.setProperty("Ice.Default.Host", interface) + self.communicator = Ice.initialize(initData) + try: + if clientPrx: + self.clientController = self.communicator.stringToProxy(clientPrx) + self.clientController = Test.Common.ControllerPrx.checkedCast(self.clientController) + self.clientOptions = self.clientController.getOptionOverrides() + else: + self.clientController = None + self.clientOptions = {} + + if serverPrx: + self.serverController = self.communicator.stringToProxy(serverPrx) + self.serverController = Test.Common.ControllerPrx.checkedCast(self.serverController) + self.serverOptions = self.serverController.getOptionOverrides() + else: + self.serverController = None + self.serverOptions = {} + except: + self.communicator.destroy() + raise + + def filterOptions(self, options): + import Ice + options = options.copy() + for (key, values) in options.items(): + for opts in [self.serverOptions, self.clientOptions]: + if hasattr(opts, key) and getattr(opts, key) is not Ice.Unset: + options[key] = [v for v in values if v in getattr(opts, key)] + return options + + def startServerSide(self, testcase, current): + if not self.serverController: + TestCaseRunner.startServerSide(self, testcase, current) + return + + import Test + current.serverTestCase = self.serverController.runTestCase(str(testcase.getMapping()), + testcase.getTestSuite().getId(), + testcase.getName()) + try: + try: + current.host = current.serverTestCase.startServerSide(self.getConfig(current)) + except Test.Common.TestCaseFailedException as ex: + current.result.writeln(ex.output) + raise RuntimeError("test failed") + except: + current.serverTestCase.destroy() + current.serverTestCase = None + raise + + def stopServerSide(self, testcase, current, success): + if not self.serverController: + TestCaseRunner.stopServerSide(self, testcase, current, success) + return + + import Test + try: + current.result.write(current.serverTestCase.stopServerSide(success)) + current.host = None + except Test.Common.TestCaseFailedException as ex: + current.result.writeln(ex.output) + raise RuntimeError("test failed") + finally: + current.serverTestCase = None + + def runClientSide(self, testcase, current): + import Test + if not self.clientController: + TestCaseRunner.runClientSide(self, testcase, current) + return + + clientTestCase = self.clientController.runTestCase(str(testcase.getMapping()), + testcase.getTestSuite().getId(), + testcase.getName()) + try: + current.result.write(clientTestCase.runClientSide(self.getConfig(current))) + except Test.Common.TestCaseFailedException as ex: + current.result.writeln(ex.output) + raise RuntimeError("test failed") + finally: + clientTestCase.destroy() + + def destroy(self): + self.communicator.destroy() + + def getConfig(self, current): + import Test + return Test.Common.Config(current.config.protocol, + current.config.mx, + current.config.serialize, + current.config.compress, + current.config.ipv6) + +class LocalDriver(Driver): + + class Current(Driver.Current): + + def __init__(self, driver, testsuite, result, index, total): + Driver.Current.__init__(self, driver, testsuite, result) + self.index = index + self.total = total + + @classmethod + def getOptions(self): + return ("", ["cross=", "workers=", "continue", "loop", "start=", "all", "all-cross", "host=", + "client=", "server=", "interface="]) + + @classmethod + def usage(self): + print("") + print("Local driver options:") + print("--cross=<mapping> Run with servers from given mapping.") + print("--workers=<count> The number of worker threads to run the tests.") + print("--start=<index> Start running the tests at the given index.") + print("--loop Run the tests in a loop.") + print("--continue Don't stop on failures.") + print("--all Run all sensible permutations of the tests.") + print("--all-cross Run all sensible permutations of cross language tests.") + print("--client=<proxy> The endpoint of the controller to run the client side.") + print("--server=<proxy> The endpoint of the controller to run the server side.") + print("--interface=<IP> The multicast interface to use to discover client/server controllers.") + + def __init__(self, options, *args, **kargs): + Driver.__init__(self, options, *args, **kargs) + + self.cross = "" + self.allCross = False + self.workers = 1 + self.continueOnFailure = False + self.loop = False + self.start = 0 + self.all = False + + self.clientCtlPrx = "" + self.serverCtlPrx = "" + self.interface = "" + + parseOptions(self, options, { "continue" : "continueOnFailure", + "l" : "loop", + "all-cross" : "allCross", + "client" : "clientCtlPrx", + "server" : "serverCtlPrx" }) + + if self.cross: + self.cross = Mapping.getByName(self.cross) + if not self.cross: + raise RuntimeError("unknown mapping `{0}' for --cross option".format(self.cross)) + + self.results = [] + self.threadlocal = threading.local() + + if self.clientCtlPrx or self.serverCtlPrx: + self.runner = RemoteTestCaseRunner(self.clientCtlPrx, self.serverCtlPrx, self.interface) + else: + self.runner = TestCaseRunner() + + def run(self, mappings): + while True: + executor = Executor(self.threadlocal, self.workers, self.continueOnFailure) + for mapping in mappings: + testsuites = mapping.getTestSuites() + + # + # Sort the test suites to run tests in the following order. + # + runOrder = mapping.getRunOrder() + def testsuiteKey(testsuite): + for k in runOrder: + if testsuite.getId().startswith(k + os.sep): + return testsuite.getId().replace(k, str(runOrder.index(k))) + return testsuite.getId() + testsuites = sorted(testsuites, key=testsuiteKey) + + # + # Create the executor to run the test suites on multiple workers thread is requested. + # + for testsuite in testsuites: + if mapping.filterTestSuite(testsuite.getId(), self.filters, self.rfilters): + continue + if testsuite.getId() == "Ice/echo": + continue + elif (self.cross or self.allCross) and not testsuite.isCross(): + continue + elif self.allCross and not testsuite.isAllCross(): + continue + elif isinstance(self.runner, RemoteTestCaseRunner) and not testsuite.isMultiHost(): + continue + executor.submit(testsuite) + + # + # Run all the tests and wait for the executor to complete. + # + now = time.time() + + results = executor.runUntilCompleted(self, self.start) + + failures = [r for r in results if not r.isSuccess()] + m, s = divmod(time.time() - now, 60) + print("") + if m > 0: + print("Ran {0} tests in {1} minutes {2:02.2f} seconds".format(len(results), m, s)) + else: + print("Ran {0} tests in {1:02.2f} seconds".format(len(results), s)) + if(len(failures) > 0): + print("{0} suceeded and {1} failed:".format(len(results) - len(failures), len(failures))) + for r in failures: + print("- {0}".format(r.testsuite)) + for (c, ex) in r.getFailed().items(): + lines = r.getOutput(c).strip().split('\n') + for i in range(0, min(4, len(lines))): + print(" " + lines[i]) + if len(lines) > 4: + print(" [...]") + for i in range(max(4, len(lines) - 8), len(lines)): + print(" " + lines[i]) + + else: + print("{0} suceeded".format(len(results))) + + if not self.loop: + break + + def destroy(self): + self.runner.destroy() + self.runner = None + + def runTestSuite(self, current): + current.result.writeln("*** [{0}/{1}] Running {2}/{3} tests ***".format(current.index, + current.total, + current.testsuite.getMapping(), + current.testsuite)) + success = False + try: + current.testsuite.setup(current) + for testcase in current.testsuite.getTestCases(): + config = current.config + try: + for conf in current.config.getAll(current, testcase) if self.all else [current.config]: + current.config = conf + testcase.run(current) + finally: + current.config = config + success = True + finally: + current.testsuite.teardown(current, success) + + def runClientServerTestCase(self, current): + + if current.testcase.getParent(): + success = False + current.testcase._startServerSide(current) + try: + current.testcase._runClientSide(current) + success = True + finally: + current.testcase._stopServerSide(current, success) + return + + client = current.testcase.getClientTestCase() + for cross in (Mapping.getAll() if self.allCross else [self.cross]): + + # Only run cross tests with allCross + if self.allCross and cross == current.testcase.getMapping(): + continue + + # If the given mapping doesn't support server-side, skip this mapping. + if cross and cross != cross.getServerMapping(): + continue + + # Skip if the mapping doesn't provide the test case. + server = current.testcase.getServerTestCase(cross) + if not server: + continue + + current.writeln("[ running {0} test ]".format(current.testcase)) + confStr = str(current.config) + if confStr: + current.writeln("- Config: {0}".format(confStr)) + if cross: + current.writeln("- Mappings: {0}/{1}".format(client.getMapping(), server.getMapping())) + + if not current.config.canRun(current): + current.writeln("skipped, not supported with this configuration") + return + + success = False + self.runner.startServerSide(server, current) + try: + self.runner.runClientSide(client, current) + success = True + finally: + self.runner.stopServerSide(server, current, success) + + def runTestCase(self, current): + if not self.cross and not self.allCross: + if not current.testcase.getParent(): + current.writeln("[ running {0} test ]".format(current.testcase)) + confStr = str(current.config) + if confStr: + current.writeln("- Config: {0}".format(confStr)) + if not current.config.canRun(current): + current.writeln("skipped, not supported with this configuration") + return + current.testcase._runClientSide(current) + + def isWorkerThread(self): + return hasattr(self.threadlocal, "num") + + def getTestPort(self, portnum): + # Return a port number in the range 14100-14199 for the first thread, 14200-14299 for the + # second thread, etc. + assert(portnum < 100) + baseport = 14000 + self.threadlocal.num * 100 if hasattr(self.threadlocal, "num") else 12010 + return baseport + portnum + + def getProps(self, process, current): + props = Driver.getProps(self, process, current) + if isinstance(process, IceProcess): + if current.host: + props["Ice.Default.Host"] = current.host + # Ice process from the bin directory don't support Test.BasePort + if not process.isFromBinDir() and hasattr(self.threadlocal, "num"): + props["Test.BasePort"] = 14000 + self.threadlocal.num * 100 + return props + + def getMappings(self): + return Mapping.getAll() if self.allCross else [self.cross] if self.cross else [] + + def filterOptions(self, testcase, options): + return self.runner.filterOptions(options) + +Driver.add("local", LocalDriver) diff --git a/scripts/NetworkProxy.py b/scripts/NetworkProxy.py index 93cc0a7328a..d161f775f9e 100644 --- a/scripts/NetworkProxy.py +++ b/scripts/NetworkProxy.py @@ -77,19 +77,29 @@ class BaseProxy(threading.Thread): threading.Thread.__init__(self) self.port = port self.closed = False - self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.cond = threading.Condition() + self.socket = None self.connections = [] atexit.register(self.terminate) self.setDaemon(True) self.start() + with self.cond: + while not self.socket: + self.cond.wait() def createConnection(self): return None def run(self): - self.socket.bind(("127.0.0.1", self.port)) - self.socket.listen(1) + with self.cond: + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + if hasattr(socket, "SO_REUSEPORT"): + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + self.socket.bind(("127.0.0.1", self.port)) + self.socket.listen(1) + self.cond.notify() + try: while not self.closed: incoming, peer = self.socket.accept() @@ -110,6 +120,7 @@ class BaseProxy(threading.Thread): c.close() except Exception as ex: print(ex) + connectToSelf = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: connectToSelf.connect(("127.0.0.1", self.port)) @@ -152,7 +163,7 @@ class SocksConnection(BaseConnection): return packet if sys.version_info[0] == 2 else bytes(packet,"ascii") class SocksProxy(BaseProxy): - + def createConnection(self, socket, peer): return SocksConnection(socket, peer) @@ -172,12 +183,12 @@ class HttpConnection(BaseConnection): sep = data.find(":") if sep < len("CONNECT ") + 1: raise InvalidRequest - + host = data[len("CONNECT "):sep] space = data.find(" ", sep) if space < sep + 1: raise InvalidRequest - + port = int(data[sep + 1:space]) return (host, port) @@ -189,6 +200,6 @@ class HttpConnection(BaseConnection): return s if sys.version_info[0] == 2 else bytes(s,"ascii") class HttpProxy(BaseProxy): - + def createConnection(self, socket, peer): return HttpConnection(socket, peer) diff --git a/scripts/TestController.py b/scripts/TestController.py deleted file mode 100644 index 718a117caa6..00000000000 --- a/scripts/TestController.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python -# ********************************************************************** -# -# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. -# -# This copy of Ice is licensed to you under the terms described in the -# ICE_LICENSE file included in this distribution. -# -# ********************************************************************** - -import os, sys, threading, subprocess, getopt, signal, re - -path = [ ".", "..", "../..", "../../..", "../../../.." ] -head = os.path.dirname(sys.argv[0]) -if len(head) > 0: - path = [os.path.join(head, p) for p in path] -path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] - -if len(path) == 0: - raise RuntimeError("can't find toplevel directory!") -sys.path.append(os.path.join(path[0], "scripts")) -import TestUtil - -def removeTrustSettings(): - serverCert = os.path.join(path[0], "certs", "server.pem") - if os.system("security verify-cert -c " + serverCert + " >& /dev/null") == 0: - sys.stdout.write("removing trust settings for the HTTP server certificate... ") - sys.stdout.flush() - if os.system("security remove-trusted-cert " + serverCert) != 0: - print("\nerror: couldn't remove trust settings for the HTTP server certificate") - else: - print("ok") - else: - print("trust settings already removed") - -# -# On OS X, provide an option to allow removing the trust settings -# -if TestUtil.isDarwin(): - try: - opts, args = getopt.getopt(sys.argv[1:], "", ["clean"]) - if ("--clean", "") in opts: - removeTrustSettings() - sys.exit(0) - except getopt.GetoptError: - pass - -props = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "java", "gradle.properties"), "r") -iceVersion = re.search("iceVersion *= *([-.0-9a-z]*)", props.read()).group(1) - -jar = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", - "java/test/controller/build/libs/testController-%(iceVersion)s.jar" % {"iceVersion": iceVersion}) - -javaHome = os.environ.get("JAVA_HOME", "") -javaCmd = '%s' % os.path.join(javaHome, "bin", "java") if javaHome else "java" -command = [javaCmd, "-jar", jar] -if len(sys.argv) > 1: - command += sys.argv[1:] - -p = subprocess.Popen(command, shell = False, stdin = subprocess.PIPE, stdout = subprocess.PIPE, - stderr = subprocess.STDOUT, bufsize = 0) - -def signal_handler(signal, frame): - if p: - p.terminate() - sys.exit(0) -signal.signal(signal.SIGINT, signal_handler) -signal.signal(signal.SIGTERM, signal_handler) - -if TestUtil.isDarwin(): - # - # On OS X, we set the trust settings on the certificate to prevent - # the Web browsers from prompting the user about the unstrusted - # certificate. Some browsers such as Chrome don't provide the - # option to set this trust settings. - # - serverCert = os.path.join(TestUtil.toplevel, "certs", "server.pem") - if os.system("security verify-cert -c " + serverCert + " >& /dev/null") != 0: - sys.stdout.write("adding trust settings for the HTTP server certificate... ") - sys.stdout.flush() - if os.system("security add-trusted-cert -r trustAsRoot " + serverCert) != 0: - print("error: couldn't add trust settings for the HTTP server certificate") - print("ok") - print("run " + sys.argv[0] + " --clean to remove the trust setting") - -while(True): - - c = p.stdout.read(1) - if not c: break - if c == '\r': continue - - # Depending on Python version and platform, the value c could be a - # string or a bytes object. - if type(c) != str: - c = c.decode() - sys.stdout.write(c) - sys.stdout.flush() diff --git a/scripts/TestUtil.py b/scripts/TestUtil.py deleted file mode 100755 index 846d9975ce6..00000000000 --- a/scripts/TestUtil.py +++ /dev/null @@ -1,2669 +0,0 @@ -# ********************************************************************** -# -# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. -# -# This copy of Ice is licensed to you under the terms described in the -# ICE_LICENSE file included in this distribution. -# -# ********************************************************************** - -import sys, os, re, getopt, time, string, threading, atexit, platform, traceback, subprocess - -# Global flags and their default values. -protocol = "" # If unset, default to TCP. Valid values are "tcp", "ssl", "ws", "wss", "bt" or "bts". -compress = False # Set to True to enable bzip2 compression. -serialize = False # Set to True to have tests use connection serialization -host = None # Will default to loopback. -debug = False # Set to True to enable test suite debugging. -mono = False # Set to True when not on Windows -keepGoing = False # Set to True to have the tests continue on failure. -ipv6 = False # Default to use IPv4 only -socksProxy = False # Use SOCKS proxy running on localhost -global x64 -x64 = False # Binary distribution is 64-bit -global x86 -x86 = False # Binary distribution is 32-bit -global armv7l -armv7l = False # Binary distribution is armv7l -cpp11 = False # Binary distribution is c++11 -es5 = False # Use JavaScript ES5 (Babel compiled code) -static = False # Static build -global buildMode -buildMode = None - -extraArgs = [] -clientTraceFilters = [] -serverTraceFilters = [] - -# Default java loader - -javaHome = os.environ.get("JAVA_HOME", "") -javaCmd = '"%s"' % os.path.join(javaHome, "bin", "java") if javaHome else "java" -javaLibraryPath = None # Used for Freeze - -valgrind = False # Set to True to use valgrind for C++ executables. -appverifier = False # Set to True to use appverifier for C++ executables, This is windows only feature -tracefile = None -printenv = False -cross = [] -watchDog = None -clientHome = None -serviceDir = None -compact = False -global winrt -winrt = False -global serverOnly -serverOnly = False -mx = False -controller = None -configName = None - -queuedTests = [] - -global additionalBinDirectories -additionalBinDirectories = [] - -def addAdditionalBinDirectories(directories): - global additionalBinDirectories - additionalBinDirectories += directories - -def resetAdditionalBinDirectories(): - global additionalBinDirectories - additionalBinDirectories = [] - -# -# Linux distribution -# -linuxDistribution = None -for path in ["/etc/redhat-release", "/etc/issue"]: - if not os.path.isfile(path): - continue - - f = open(path, "r") - issue = f.read() - f.close() - - if issue.find("Red Hat") != -1: - linuxDistribution = "RedHat" - elif issue.find("Amazon Linux") != -1: - linuxDistribution = "Amazon" - elif issue.find("CentOS") != -1: - linuxDistribution = "CentOS" - elif issue.find("Ubuntu") != -1: - linuxDistribution = "Ubuntu" - elif issue.find("Debian") != -1: - linuxDistribution = "Debian" - elif issue.find("SUSE Linux") != -1: - linuxDistribution = "SUSE LINUX" - elif issue.find("Yocto") != -1: - linuxDistribution = "Yocto" - -def isCygwin(): - # The substring on sys.platform is required because some cygwin - # versions return variations like "cygwin_nt-4.01". - return sys.platform[:6] == "cygwin" - -def isWin32(): - return sys.platform == "win32" or isCygwin() - -def isVista(): - return isWin32() and sys.getwindowsversion()[0] == 6 and sys.getwindowsversion()[1] == 0 - -def isWin9x(): - if isWin32(): - return not ("OS" in os.environ and os.environ["OS"] == "Windows_NT") - else: - return 0 - -def isSolaris(): - return sys.platform == "sunos5" - -def isSparc(): - p = subprocess.Popen("uname -p", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) - if not p or not p.stdout: - print("unable to get system information!") - sys.exit(1) - l = p.stdout.readline().decode("utf-8").strip() - if l == "sparc": - return True - else: - return False - -def dpkgHostMultiArch(): - p = subprocess.Popen("dpkg-architecture -qDEB_HOST_MULTIARCH", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) - if not p or not p.stdout: - print("unable to get system information!") - sys.exit(1) - return p.stdout.readline().decode("utf-8").strip() - -def isI686(): - return x86 or any(platform.machine() == p for p in ["i386", "i686"]) - -def isAIX(): - return sys.platform.startswith("aix") - -def isDarwin(): - return sys.platform == "darwin" - -def isLinux(): - return sys.platform.startswith("linux") or sys.platform.startswith("gnukfreebsd") - -def isUbuntu(): - return isLinux() and linuxDistribution and linuxDistribution == "Ubuntu" - -def isRhel(): - return isLinux() and linuxDistribution in ["RedHat", "Amazon", "CentOS"] - -def isYocto(): - return isLinux() and linuxDistribution and linuxDistribution == "Yocto" - -def isDebian(): - return isLinux() and linuxDistribution and linuxDistribution == "Debian" - -def isSles(): - return isLinux() and linuxDistribution and linuxDistribution == "SUSE LINUX" - -def iceUseOpenSSL(): - return any(sys.platform.startswith(p) for p in ["linux", "freebsd"]) - -def getCppCompiler(): - compiler = "" - if os.environ.get("CPP_COMPILER", "") != "": - compiler = os.environ["CPP_COMPILER"] - elif isMINGW(): - compiler = "MINGW" - else: - p = subprocess.Popen("cl", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) - if not p or not p.stdout: - print("Cannot detect C++ compiler") - compiler = VC120 - else: - l = p.stdout.readline().decode("utf-8").strip() - if l.find("Version 16.") != -1: - compiler = "VC100" - elif l.find("Version 17.") != -1: - compiler = "VC110" - elif l.find("Version 18.") != -1: - compiler = "VC120" - elif l.find("Version 19.") != -1: - compiler = "VC140" - else: - # - # Cannot detect C++ compiler use default - # - compiler = "VC140" - return compiler - -def isMINGW(): - if not isWin32(): - return False - # Ruby Installer DEVKIT sets the RI_DEVKIT environment variable, - # we check for this variable to detect the Ruby MINGW environment. - return "RI_DEVKIT" in os.environ - -def isVC100(): - if not isWin32(): - return False - return getCppCompiler() == "VC100" - -def isVC110(): - if not isWin32(): - return False - return getCppCompiler() == "VC110" - -def isVC120(): - if not isWin32(): - return False - return getCppCompiler() == "VC120" - -def isVC140(): - if not isWin32(): - return False - return getCppCompiler() == "VC140" - -def getIceSoVersion(): - config = open(os.path.join(toplevel, "cpp", "include", "IceUtil", "Config.h"), "r") - intVersion = int(re.search("ICE_INT_VERSION ([0-9]*)", config.read()).group(1)) - majorVersion = int(intVersion / 10000) - minorVersion = int(intVersion / 100) - 100 * majorVersion - patchVersion = intVersion % 100 - if patchVersion < 50: - return '%d' % (majorVersion * 10 + minorVersion) - elif patchVersion < 60: - return '%da%d' % (majorVersion * 10 + minorVersion, patchVersion - 50) - else: - return '%db%d' % (majorVersion * 10 + minorVersion, patchVersion - 60) - -def getIceJsonVersion(): - r = re.search(r"([0-9]+)\.([0-9]+)(\.[0-9]+|[ab][0-9]+)", iceVersion) - major = int(r.group(1)) - minor = int(r.group(2)) - v = ("%d.%d" % (major, minor)).strip() - if r.group(3).startswith("a"): - return v + ".0-" + r.group(3).replace("a", "alpha").strip() - elif r.group(3).startswith("b"): - return v + ".0-" + r.group(3).replace("b", "beta").strip() - else: - return ("%s%s" % (v, r.group(3))).strip() - -def getJdkVersion(): - process = subprocess.Popen("java -version", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) - if not process or not process.stdout: - print("unable to get Java version!") - sys.exit(1) - global jdkVersion - jdkVersion = process.stdout.readline() - if not jdkVersion: - print("unable to get Java version!") - sys.exit(1) - return jdkVersion.decode("utf-8") - -def getWinRegistryKeyValue(key, subKey): - import winreg - try: - key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key, 0, winreg.KEY_READ | winreg.KEY_WOW64_64KEY) - try: - return winreg.QueryValueEx(key, subKey) - finally: - winreg.CloseKey(key) - except: - pass - -def sanitize(cp): - np = "" - for p in cp.split(os.pathsep): - if len(np) > 0: - np = np + os.pathsep - np = np + p - return np - -def quoteArgument(arg): - if arg is None: - return None - return '"%s"' % arg - -def dumpenv(env, lang): - if env is None: - env = os.environ - vars = ["PATH", "LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH", "SHLIB_PATH", "LIBPATH", "LD_LIBRARY_PATH_64"] - if lang is None: - vars.extend(["CLASSPATH", "MONO_PATH", "DEVPATH", "PYTHONPATH", "RUBYLIB"]) - elif lang == "cpp": - pass - elif lang == "java" or lang == "java-compat": - vars.append("CLASSPATH") - elif lang == "csharp": - vars.extend(["MONO_PATH", "DEVPATH"]) - elif lang == "python": - vars.append("PYTHONPATH") - elif lang == "ruby": - vars.append("RUBYLIB") - elif lang == "js": - vars.append("NODE_PATH") - for i in vars: - if i in env: - print("%s=%s" % (i, env[i])) - -def addLdPath(libpath, env = None): - if env is None: - env = os.environ - if isWin32(): - addPathToEnv("PATH", libpath, env) - elif isDarwin(): - addPathToEnv("DYLD_LIBRARY_PATH", libpath, env) - elif isAIX(): - addPathToEnv("LIBPATH", libpath, env) - else: - addPathToEnv("LD_LIBRARY_PATH", libpath, env) - addPathToEnv("LD_LIBRARY_PATH_64", libpath, env) - return env - -def addClasspath(path, env = None): - return addPathToEnv("CLASSPATH", path, env) - -def addPathToEnv(variable, path, env = None): - if env is None: - env = os.environ - if variable not in env: - env[variable] = path - else: - env[variable] = path + os.pathsep + env.get(variable) - return env - -# -# This is set by the choice of init method. If not set, before it is -# used, it indicates a bug and things should terminate. -# -defaultMapping = None -testErrors = [] -toplevel = None -testToplevel = None - -path = [ ".", "..", "../..", "../../..", "../../../..", "../../../../..", "../../../../../..", - "../../../../../../..", "../../../../../../../..", "../../../../../../../../.." ] -head = os.path.dirname(sys.argv[0]) -if len(head) == 0: - head = "." -# Try to find scripts/TestUtil.py or ice/scripts/TestUtil.py in parent directories -path = [os.path.join(head, p) for p in path] + [os.path.join(head, p, "ice") for p in path] -path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] -if len(path) == 0: - raise RuntimeError("can't find toplevel directory!") -toplevel = path[0] -testToplevel = toplevel - -# -# Set the default arch to x64 on x64 machines, this could be overriden -# with the --x86 command line argument. -# -if isWin32(): - if os.environ.get("PLATFORM", "").upper() == "X64": - x64 = True -elif isAIX(): - if os.environ.get("OBJECT_MODE", "") == "64": - x64 = True -else: - p = subprocess.Popen("uname -m", shell = True, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) - if(p.wait() != 0): - print("uname failed:\n" + p.stdout.read().strip()) - sys.exit(1) - line = p.stdout.readline().decode('UTF-8').strip() - if line == "x86_64" and os.environ.get("LP64", "") != "no": - x64 = True - elif line == "armv7l": - armv7l = True - -# -# The PHP interpreter is called "php5" on some platforms (e.g., SLES). -# -phpCmd = "php" -for path in os.environ["PATH"].split(os.pathsep): - # - # Stop if we find "php" in the PATH first. - # - if os.path.exists(os.path.join(path, "php")): - break - elif os.path.exists(os.path.join(path, "php5")): - phpCmd = "php5" - break - -# -# The NodeJS interpreter is called "nodejs" on some platforms -# (e.g., Ubuntu) -# -nodeCmd = "node" -if "NODE" in os.environ: - nodeCmd = os.environ["NODE"] -else: - for path in os.environ["PATH"].split(os.pathsep): - # - # Stop if we find "node" in the PATH first. - # - if os.path.exists(os.path.join(path, "node")): - break - elif os.path.exists(os.path.join(path, "nodejs")): - nodeCmd = "nodejs" - break - -# -# Figure out the Ice version -# -iceVersion = None -try: - if isWin32(): - config = open(os.path.join(toplevel, "config", "icebuilder.props"), "r") - iceVersion = re.search("<IceVersion>[\t\s]*([0-9]+\.[0-9]+(\.[0-9]+|[ab][0-9]*))</IceVersion>", config.read()).group(1) - else: - config = open(os.path.join(toplevel, "config", "Make.rules"), "r") - iceVersion = re.search("version[\t\s]*= ([0-9]+\.[0-9]+(\.[0-9]+|[ab][0-9]*))", config.read()).group(1) - config.close() -except: - print("error: couldn't figure Ice version") - sys.exit(1) - -# -# Figure out Ice installation directory -# -iceHome = None # Binary distribution to use (or None to use binaries from source distribution) -if os.environ.get("USE_BIN_DIST", "no") == "yes": - # Only use binary distribution from ICE_HOME environment variable if USE_BIN_DIST=yes - if os.environ.get("ICE_HOME", "") != "": - iceHome = os.environ["ICE_HOME"] - elif isLinux(): - iceHome = "/usr" - elif isDarwin(): - iceHome = "/usr/local" - elif isWin32(): - path = getWinRegistryKeyValue("SOFTWARE\\ZeroC\\Ice %s" % iceVersion, "InstallDir") - if path and len(path) > 0 and os.path.exists(path[0]): - iceHome = path[0] - -# List of supported cross-language tests. -crossTests = [ #"Ice/adapterDeactivation", - #"Ice/background", - #"Ice/binding", - #"Ice/checksum", - #"Ice/custom", - "Ice/ami", - "Ice/info", - "Ice/exceptions", - "Ice/enums", - "Ice/facets", - #"Ice/hold", - "Ice/inheritance", - "Ice/invoke", - #"Ice/location", - "Ice/objects", - "Ice/operations", - "Ice/proxy", - #"Ice/retry", - "Ice/servantLocator", - #"Ice/timeout", - "Ice/slicing/exceptions", - "Ice/slicing/objects", - "Ice/optional", - ] - -def run(tests, root = False): - def usage(): - print("usage: " + sys.argv[0] + """ - --all Run all sensible permutations of the tests. - --all-cross Run all sensible permutations of cross language tests. - --start=index Start running the tests at the given index. - --loop Run the tests in a loop. - --filter=<regex> Run all the tests that match the given regex. - --rfilter=<regex> Run all the tests that do not match the given regex. - --debug Display debugging information on each test. - --protocol=<prot> Run with the given protocol (tcp|ssl|ws|wss|bt). - --compress Run the tests with protocol compression. - --host=host Set --Ice.Default.Host=<host>. - --valgrind Run the test with valgrind. - --appverifier Run the test with appverifier under Windows. - --serialize Run with connection serialization. - --continue Keep running when a test fails. - --ipv6 Use IPv6 addresses. - --socks Use SOCKS proxy running on localhost. - --no-ipv6 Don't use IPv6 addresses. - --ice-home=<path> Use the binary distribution from the given path. - --mode=debug|release Run the tests with debug or release mode builds (win32 only)." - --x86 Binary distribution is 32-bit. - --x64 Binary distribution is 64-bit. - --c++11 Binary distribution is c++11. - --es5 Use JavaScript ES5 (Babel compiled code) - --static Binary distribution is static. - --cross=lang Run cross language test. - --client-home=<dir> Run cross test clients from the given Ice source distribution. - --script Generate a script to run the tests. - --env Print important environment variables. - --service-dir=<dir> Where to locate services for builds without service support. - --compact Ice for .NET uses the Compact Framework. - --winrt Run server with configuration suited for WinRT client. - --server Run only the server. - --mx Enable IceMX when running the tests. - --controller=<host> Use the test controller on the specified host. - --arg=<property> Append the given argument. - """) - sys.exit(2) - - try: - opts, args = getopt.getopt(sys.argv[1:], "lr:R:", - ["start=", "start-after=", "filter=", "rfilter=", "all", "all-cross", "loop", - "debug", "protocol=", "compress", "valgrind", "host=", "serialize", "continue", - "ipv6", "no-ipv6", "socks", "ice-home=", "mode=", "cross=", "client-home=", "x64", "x86", - "script", "env", "arg=", "service-dir=", "appverifier", "compact", - "winrt", "server", "mx", "c++11", "es5", "static", "controller=", "configName="]) - except getopt.GetoptError: - usage() - - if args: - usage() - - start = 0 - loop = False - all = False - allCross = False - arg = "" - script = False - noipv6 = False - compact = "--compact" in opts - winrt = "--winrt" in opts - serverOnly = "--server" in opts - mx = "--mx" in opts - controller = "--controller" in opts - configName = "--configName" in opts - - filters = [] - for o, a in opts: - if o == "--continue": - global keepGoing - keepGoing = True - elif o in ("-l", "--loop"): - loop = True - elif o in ("-r", "-R", "--filter", '--rfilter'): - testFilter = re.compile(re.escape(os.path.normpath(a))) - if o in ("--rfilter", "-R"): - filters.append((testFilter, True)) - else: - filters.append((testFilter, False)) - elif o == "--cross": - global cross - crossLang = ["cpp", "csharp", "java", "java-compat", "js", "php", "python", "ruby", "objective-c"] - if a not in crossLang: - print("cross must be one of %s" % ', '.join(crossLang)) - sys.exit(1) - cross.append(a) - elif o == "--all" : - all = True - elif o == "--no-ipv6" : - noipv6 = True - elif o == "--all-cross" : - allCross = True - elif o in '--start': - start = int(a) - elif o == "--script": - script = True - elif o == '--arg': - arg += " --arg=" - arg += '"' - arg += a - arg += '"' - elif o == "--protocol": - if a not in ("bt", "bts", "ws", "wss", "ssl", "tcp"): - usage() - if not root and getDefaultMapping() == "csharp" and (a == "ssl" or a == "wss"): - if mono: - print("SSL is not supported with mono") - sys.exit(1) - if compact: - print("SSL is not supported with the Compact Framework") - sys.exit(1) - if a in ["bt", "bts"] and not isLinux(): - print("Bluetooth is only supported on Linux") - sys.exit(1) - elif o == "--c++11": - global cpp11 - cpp11 = True - elif o == "--es5": - global es5 - es5 = True - elif o == "--static": - global static - static = True - elif o == "--x86": - global x86 - x86 = True - elif o == "--x64": - global x64 - x64 = True - if o in ( "--cross", "--protocol", "--host", "--debug", "--compress", "--valgrind", "--serialize", "--ipv6", \ - "--socks", "--ice-home", "--mode", "--x86", "--x64", "--c++11", "--es5", "--static", "--env", \ - "--service-dir", "--appverifier", "--compact", "--winrt", \ - "--server", "--mx", "--client-home", "--controller", "--configName"): - arg += " " + o - if len(a) > 0: - arg += " " + a - - if not root: - tests = [ (os.path.join(getDefaultMapping(), "test", os.path.normpath(x)), y) for x, y in tests ] - - # Expand all the test and argument combinations. - expanded = [] - if all: - expanded.append([(test, arg, config) for test,config in tests if "once" in config ]) - - a = '--protocol=tcp %s' % arg - expanded.append([ (test, a, config) for test,config in tests if "core" in config]) - - a = '--protocol=ssl %s' % arg - expanded.append([ (test, a, config) for test,config in tests if "core" in config]) - - a = '--protocol=ws %s' % arg - expanded.append([ (test, a, config) for test,config in tests if "core" in config]) - - if not noipv6: - a = "--ipv6 --protocol=wss --compress --mx --serialize %s" % arg - expanded.append([ (test, a, config) for test,config in tests if "core" in config]) - - a = "--protocol=tcp %s" % arg - expanded.append([ (test, a, config) for test,config in tests if "service" in config]) - - if not noipv6: - a = "--ipv6 --protocol=ssl --compress --mx --serialize %s" % arg - expanded.append([ (test, a, config) for test,config in tests if "service" in config]) - - elif not allCross: - expanded.append([ (test, arg, config) for test,config in tests]) - - if allCross: - if len(cross) == 0: - cross = ["cpp", "java", "java-compat", "js", "php", "python", "ruby"] - if isWin32(): - cross.append("csharp") - - # PHP/Python only build with VC140 - if getCppCompiler() != "VC140": - cross.remove('php') - cross.remove('python') - - # TODO: We're currently not building Ruby on Windows - cross.remove('ruby') - if isDarwin(): - cross.append("objective-c") - if root: - allLang = ["cpp", "java", "java-compat", "js", "python"] - if isWin32(): - allLang.append("csharp") - if isDarwin(): - allLang.append("objective-c") - else: - allLang = [ getDefaultMapping() ] - for lang in allLang: - # js test user server for other language so we can ignore this - if lang == "js": - continue - - # Run each crossLang through the remove filters. Does not support filter. - # We do this so that we can filter out cross language tests if necessary. - def langFiltered(lang): - for testFilter, removeFilter in filters: - if removeFilter and testFilter.search(lang): - return True - return False - - # This is all other languages than the current mapping. - crossLang = [ l for l in cross if lang != l and langFiltered(l) == False] - - # This is all eligible cross tests for the current mapping. - # Now expand out the tests. We run only tcp for most cross tests. - for c in crossLang: - a = "--cross=%s --protocol=tcp %s" % (c, arg) - for test in crossTests: - name = os.path.join(lang, "test", test) - expanded.append([(name, a, testConfig(name, tests))]) - - # Add ssl & compress for the operations test. - if ((compact or mono) and c == "csharp") or (c == "js"): # Don't add the ssl tests. - continue - a = "--cross=%s --protocol=ssl --compress %s" % (c, arg) - expanded.append([(os.path.join(lang, "test", "Ice", "operations"), a, [])]) - - # Apply filters after expanding. - if len(filters) > 0: - for testFilter, removeFilter in filters: - nexpanded = [] - for tests in expanded: - if removeFilter: - nexpanded.append([ (x, a, y) for x,a,y in tests if not testFilter.search(x) ]) - else: - nexpanded.append([ (x, a, y) for x,a,y in tests if testFilter.search(x) ]) - expanded = nexpanded - - if loop: - num = 1 - while 1: - runTests(start, expanded, num, script = script) - num += 1 - else: - runTests(start, expanded, script = script) - - global testErrors - if len(testErrors) > 0: - print("The following errors occurred:") - for x in testErrors: - print(x) - -if not isWin32(): - mono = True - -def testConfig(name, tests): - for i in tests: - if i[0] == name: - return i[1] - return [] - -def getIceDir(subdir = None, testdir = None): - # - # If client-home is set and if the given test directory is from a - # sub-directory of the client home directory, run the test against - # the client-home source distribution. - # - global clientHome - if testdir and clientHome and os.path.commonprefix([testdir, clientHome]) == clientHome: - return os.path.join(clientHome, subdir) - - # - # If ICE_HOME is set we're running the test against a binary distribution. Otherwise, - # we're running the test against a source distribution. - # - global iceHome - if iceHome: - return iceHome - elif subdir: - return os.path.join(toplevel, subdir) - else: - return toplevel - -def getSliceDir(): - # - # If ICE_HOME is set we're running the test against a binary distribution. Otherwise, - # we're running the test against a source distribution. - # - global iceHome - if iceHome: - if iceHome == "/usr/local" or iceHome == "/usr": - return os.path.join(iceHome, "ice", "slice") - else: - return os.path.join(iceHome, "slice") - else: - return os.path.join(toplevel, "slice") - -def phpCleanup(): - if os.path.exists("ice.profiles"): - os.remove("ice.profiles") - -def phpProfileSetup(clientConfig = False, iceOptions = None, iceProfile = None): - interpreterOptions = [] - - if iceProfile != None: - atexit.register(phpCleanup) - interpreterOptions.append("-d ice.profiles='ice.profiles'") - tmpProfiles = open("ice.profiles", "w") - tmpProfiles.write("[%s]\n" % iceProfile) - if clientConfig: - tmpProfiles.write("ice.config=\"config.client\"\n") - if iceOptions != None: - tmpProfiles.write("ice.options=\"%s\"\n" % iceOptions) - tmpProfiles.close() - else: - if clientConfig: - interpreterOptions.append("-d ice.config='config.client'") - if iceOptions != None: - interpreterOptions.append("-d ice.options='%s'" % iceOptions) - - return ' '.join(interpreterOptions) - -def phpFlags(): - flags = [] - extDir = None - ext = None - incDir = None - - if isWin32(): - ext = "php_ice.dll" - if not iceHome: - extDir = os.path.abspath(os.path.join(getIceDir("php"), "lib", "x64" if x64 else "Win32", - "Debug" if buildMode == "debug" else "Release")) - incDir = os.path.abspath(os.path.join(getIceDir("php"), "lib")) - else: - extDir = os.path.join(iceHome, "php") - incDir = extDir - else: - ext = "IcePHP.so" - if not iceHome: - extDir = os.path.abspath(os.path.join(toplevel, "php", "lib")) - incDir = extDir - else: - # - # If ICE_HOME points to the installation directory of a source build, the - # PHP extension will be located in $ICE_HOME/php. For an RPM installation, - # the extension should already be in PHP's default extension directory so - # we don't need to set extension_dir. - # - # We start PHP with "php -n". The -n option causes PHP to ignore its - # default configuration file(s). We do this to suppress any warnings - # that PHP might generate when it can't find its default extensions after - # we modify extension_dir. Even if we don't define extension_dir, we still - # need to add "extension = IcePHP.<ext>". - # - extDir = os.path.join(iceHome, "php") - incDir = extDir - - if not os.path.exists(os.path.join(extDir, ext)): - if iceHome == "/usr": - extDir = None # Assume the extension is already in PHP's extension_dir. - # - # On SLES11, the PHP run time files are installed in /usr/share/php5, but - # this directory is not in the default include path when you specify an - # alternate configuration file, so we have to configure it explicitly. - # - if os.path.exists("/usr/share/php5/Ice.php"): - incDir = "/usr/share/php5" - else: - incDir = None - elif iceHome == "/usr/local" and isDarwin(): - extDir = "/usr/local/lib/php/extensions" - incDir = "/usr/local/share/php" - else: - print("unable to find IcePHP extension!") - sys.exit(1) - - if extDir: - flags.append("-d extension_dir='%s'" % extDir) - flags.append("-d extension='%s'" % ext) - if incDir: - flags.append("-d include_path='%s'" % incDir) - - return ' '.join(flags) - -def getIceBox(): - global cpp11 - - # - # Get and return the path of the IceBox executable - # - lang = getDefaultMapping() - if lang == "cpp": - iceBox = "icebox" - if isWin32(): - if cpp11: - iceBox += "++11" - iceBox += ".exe" - elif isLinux(): - if isI686(): - iceBox += "32" - if cpp11: - iceBox += "++11" - elif isDarwin and cpp11: - iceBox += "++11" - iceBox = os.path.join(getCppBinDir(lang), iceBox) - elif lang == "java": - iceBox = "com.zeroc.IceBox.Server" - elif lang == "java-compat": - iceBox = "IceBox.Server" - elif lang == "csharp": - iceBox = os.path.join(getIceDir("csharp"), "bin", "iceboxnet") - - return iceBox - -def getIceBoxAdmin(): - if getDefaultMapping() == "java": - return "com.zeroc.IceBox.Admin" - elif getDefaultMapping() == "java-compat": - return "IceBox.Admin" - else: - return getIceExe("iceboxadmin") - -def getIceGridAdmin(): - return getIceExe("icegridadmin") - -def getIceStormAdmin(): - return getIceExe("icestormadmin") - -def getIceGridNode(): - return getIceExe("icegridnode") - -def getIceGridRegistry(): - return getIceExe("icegridregistry") - -def getGlacier2Router(): - return getIceExe("glacier2router") - -def getIceExe(name): - if isMINGW(): - return os.path.join(getServiceDir(), name) - else: - return os.path.join(getCppBinDir(), name) - -def getNodeCommand(): - return nodeCmd - -# -# Create a passwords file that contains the given users/passwords using icehashpassword.py -# -def hashPasswords(filePath, entries): - if os.path.exists(filePath): - os.remove(filePath) - passwords = open(filePath, "a") - - command = "%s %s" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "icehashpassword.py"))) - - # - # For Linux ARM default rounds makes test slower (Usually runs on embbeded boards) - # - if isLinux() and armv7l: - command += " --rounds 100000" - - for user, password in entries.items(): - p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE) - p.stdin.write(password.encode('UTF-8')) - p.stdin.write('\r\n'.encode('UTF-8')) - p.stdin.flush() - if(p.wait() != 0): - print("icehashpassword.py failed:\n" + p.stdout.read().decode('UTF-8').strip()) - passwords.close() - sys.exit(1) - passwords.write("%s %s\n" % (user, p.stdout.readline().decode('UTF-8').strip())) - passwords.close() - -class InvalidSelectorString(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - -sslConfigTree = { - "cpp" : { - "plugin" : " --Ice.Plugin.IceSSL=IceSSL:createIceSSL --IceSSL.Password=password " + - "--IceSSL.DefaultDir=%(certsdir)s --IceSSL.CAs=cacert.pem --IceSSL.VerifyPeer=%(verifyPeer)s", - "client" : " --IceSSL.CertFile=client.p12", - "server" : " --IceSSL.CertFile=server.p12", - "colloc" : " --IceSSL.CertFile=client.p12" - }, - "java" : { - "plugin" : " --Ice.Plugin.IceSSL=com.zeroc.IceSSL.PluginFactory " + - "--IceSSL.DefaultDir=%(certsdir)s --IceSSL.Password=password --IceSSL.VerifyPeer=%(verifyPeer)s", - "client" : " --IceSSL.Keystore=client.jks", - "server" : " --IceSSL.Keystore=server.jks", - "colloc" : " --IceSSL.Keystore=client.jks" - }, - "java-compat" : { - "plugin" : " --Ice.Plugin.IceSSL=IceSSL.PluginFactory " + - "--IceSSL.DefaultDir=%(certsdir)s --IceSSL.Password=password --IceSSL.VerifyPeer=%(verifyPeer)s", - "client" : " --IceSSL.Keystore=client.jks", - "server" : " --IceSSL.Keystore=server.jks", - "colloc" : " --IceSSL.Keystore=client.jks" - }, - "csharp" : { - "plugin" : " --Ice.Plugin.IceSSL=%(icesslcs)s:IceSSL.PluginFactory --IceSSL.CAs=cacert.pem " + - "--IceSSL.Password=password --IceSSL.DefaultDir=%(certsdir)s --IceSSL.VerifyPeer=%(verifyPeer)s", - "client" : " --IceSSL.CertFile=client.p12 --IceSSL.CheckCertName=0", - "server" : " --IceSSL.CertFile=server.p12", - "colloc" : " --IceSSL.CertFile=client.p12 --IceSSL.CheckCertName=0" - }, - } - -if isDarwin(): - sslConfigTree["cpp"]["client"] += " --IceSSL.Keychain=client.keychain --IceSSL.KeychainPassword=password" - sslConfigTree["cpp"]["server"] += " --IceSSL.Keychain=server.keychain --IceSSL.KeychainPassword=password" - sslConfigTree["cpp"]["colloc"] += " --IceSSL.Keychain=colloc.keychain --IceSSL.KeychainPassword=password" - -if isWin32(): - # - # This cipher suites doesn't work well between Java and SChannel TLS1.2 implementations. - # - for lang in ["java", "java-compat"]: - sslConfigTree[lang]["client"] += " --IceSSL.Ciphers=!TLS_DHE_RSA_WITH_AES_128_GCM_SHA256" - sslConfigTree[lang]["server"] += " --IceSSL.Ciphers=!TLS_DHE_RSA_WITH_AES_128_GCM_SHA256" - -sslConfigTree["python"] = sslConfigTree["cpp"] -sslConfigTree["ruby"] = sslConfigTree["cpp"] -sslConfigTree["php"] = sslConfigTree["cpp"].copy() -sslConfigTree["objective-c"] = sslConfigTree["cpp"] - -def getDefaultMapping(): - """Try to guess the language mapping from the current path""" - # here = os.getcwd().split(os.sep) - # here.reverse() - here = os.path.relpath(os.getcwd(), start=toplevel).split(os.sep) - for i in range(0, len(here)): - if here[i] in ["cpp", "csharp", "java", "java-compat", "js", "php", "python", "ruby", "objective-c", "tmp"]: - return here[i] - raise RuntimeError("cannot determine mapping") - -def getStringIO(): - if sys.version_info[0] == 2: - import StringIO - return StringIO.StringIO() - else: - import io - return io.StringIO() - -class DriverConfig: - lang = None - protocol = None - compress = 0 - serialize = 0 - host = None - mono = False - valgrind = False - appverifier = False - type = None - overrides = None - ipv6 = False - socksProxy = False - x64 = False - x86 = False - cpp11 = False - es5 = False - static = False - serviceDir = None - mx = False - controller = None - extraArgs = [] - - def __init__(self, type = None): - global protocol - global compress - global serialize - global host - global mono - global valgrind - global appverifier - global ipv6 - global socksProxy - global x64 - global x86 - global cpp11 - global es5 - global static - global serviceDir - global compact - global mx - global controller - global extraArgs - self.lang = getDefaultMapping() - self.protocol = protocol - self.compress = compress - self.serialize = serialize - self.host = host - self.mono = mono - self.valgrind = valgrind - self.appverifier = appverifier - self.type = type - self.ipv6 = ipv6 - self.socksProxy = socksProxy - self.x64 = x64 - self.x86 = x86 - self.cpp11 = cpp11 - self.es5 = es5 - self.static = static - self.serviceDir = serviceDir - self.compact = compact - self.mx = mx - self.controller = controller - self.extraArgs = extraArgs - -def argsToDict(argumentString, results): - """Converts an argument string to dictionary""" - args = argumentString.strip() - while len(args) > 0: - end = args.find(" --") - if end == -1: - current = args.strip() - args = "" - else: - current = args[:end].strip() - args = args[end:].strip() - - value = current.find("=") - if value != -1: - results[current[:value]] = current[value+1:] - else: - results[current] = None - return results - -def getCommandLineProperties(exe, config, cfgName): - - # - # Command lines are built up from the items in the components - # sequence, which is initialized with command line options common to - # all test drivers. - # - components = ["--Ice.NullHandleAbort=1", "--Ice.Warn.Connections=1"] - - if config.lang == "cpp": - components.append("--Ice.CollectObjects=1") - - # - # Turn on network tracing. - # - #components.append("--Ice.Trace.Network=3") - #components.append("--Ice.Trace.Protocol=1") - - # - # Now we add additional components depending on the desired configuration. - # - if config.protocol in ["ssl", "wss", "bts"]: - sslenv = {} - sslenv["icesslcs"] = quoteArgument("\\\"" + os.path.join(getIceDir("csharp"), "Assemblies", "IceSSL.dll") + "\\\"") - sslenv["certsdir"] = quoteArgument(os.path.abspath(os.path.join(toplevel, "certs"))) - if winrt or config.protocol == "wss": - sslenv["verifyPeer"] = "0" - else: - sslenv["verifyPeer"] = "2" - components.append(sslConfigTree[config.lang]["plugin"] % sslenv) - components.append(sslConfigTree[config.lang][config.type] % sslenv) - - if config.protocol in ["bt", "bts"]: - components.append("--Ice.Plugin.IceBT=IceBT:createIceBT") - - components.append("--Ice.Default.Protocol=" + config.protocol) - - if config.compress: - components.append("--Ice.Override.Compress=1") - - if config.serialize: - components.append("--Ice.ThreadPool.Server.Serialize=1") - - # - # TODO - # config.lang == "cpp" required with C++11 mapping, we should be able to ged rid - # of this once AsyncResult is optimized to not required a thread pool thread with - # collocated calls and C++11 mapping. We must also check if it still required for - # python. - # - if (config.type == "server" or config.type == "colloc" and - (config.lang == "python" or config.lang == "cpp")): - components.append("--Ice.ThreadPool.Server.Size=1") - components.append("--Ice.ThreadPool.Server.SizeMax=3") - components.append("--Ice.ThreadPool.Server.SizeWarn=0") - - if config.type == "server": - components.append("--Ice.PrintAdapterReady=1") - - if config.mx: - if config.type == "server": - components.append("--Ice.Admin.Endpoints=tcp") - components.append("--Ice.Admin.InstanceName=Server") - else: - components.append("--Ice.Admin.Endpoints=tcp") - components.append("--Ice.Admin.InstanceName=Client") - - components.append("--IceMX.Metrics.Debug.GroupBy=id") - components.append("--IceMX.Metrics.Parent.GroupBy=parent") - components.append("--IceMX.Metrics.All.GroupBy=none") - - if config.controller: - components.append("--ControllerHost=" + config.controller) - - if cfgName: - components.append("--ConfigName=" + cfgName) - - if config.socksProxy: - components.append("--Ice.SOCKSProxyHost=127.0.0.1") - - if config.ipv6: - components.append("--Ice.IPv4=1 --Ice.IPv6=1 --Ice.PreferIPv6Address=1") - if config.host == None: - components.append("--Ice.Default.Host=0:0:0:0:0:0:0:1") - else: - if not config.protocol in ["bt", "bts"]: - components.append("--Ice.IPv4=1 --Ice.IPv6=0") - if config.host == None and not config.protocol in ["bt", "bts"]: - components.append("--Ice.Default.Host=127.0.0.1") - - if config.host != None and len(config.host) != 0: - components.append("--Ice.Default.Host=%s" % config.host) - - for arg in config.extraArgs: - components.append('--' + arg) - - # - # Not very many tests actually require an option override, so not too worried - # about optimal here. - # - if config.overrides != None and len(config.overrides) > 0: - propTable = {} - for c in components: - argsToDict(c, propTable) - - argsToDict(config.overrides, propTable) - components = [] - for k, v in propTable.items(): - if v != None: - components.append("%s=%s" % (k, v)) - else: - components.append("%s" % k) - - output = getStringIO() - for c in components: - output.write(c + " ") - properties = output.getvalue() - output.close() - return properties - -def getCommandLine(exe, config, options = "", interpreterOptions = "", cfgName = None): - output = getStringIO() - - if config.mono and config.lang == "csharp": - output.write("mono --debug '%s.exe' " % exe) - elif config.lang == "ruby" and config.type == "client": - # - # If running with a binary distribution ensure rubygems - # are enabled - # - if iceHome: - output.write("ruby -rubygems") - else: - output.write("ruby") - if interpreterOptions: - output.write(" " + interpreterOptions) - output.write(' "%s" ' % exe) - elif config.lang == "java" or config.lang == "java-compat": - output.write("%s -ea " % javaCmd) - if isSolaris() and config.x64: - output.write("-d64 ") - if not config.ipv6: - output.write("-Djava.net.preferIPv4Stack=true ") - if javaLibraryPath: - output.write("-Djava.library.path=" + javaLibraryPath) - if interpreterOptions: - output.write(" " + interpreterOptions) - output.write(" " + exe + " ") - elif config.lang == "python": - output.write(sys.executable) - if interpreterOptions: - output.write(" " + interpreterOptions) - output.write(' "%s" ' % exe) - elif config.lang == "php" and config.type == "client": - output.write(phpCmd + " -n %s" % phpFlags()) - if interpreterOptions: - output.write(" " + interpreterOptions) - output.write(" -f \""+ exe +"\" -- ") - elif config.lang == "js": - output.write(nodeCmd) - if interpreterOptions: - output.write(" " + interpreterOptions) - output.write(' "%s" ' % exe) - elif config.lang == "cpp" and config.valgrind: - # --child-silent-after-fork=yes is required for the IceGrid/activator test where the node - # forks a process with execv failing (invalid exe name). - output.write("valgrind -q --child-silent-after-fork=yes --leak-check=full ") - output.write('--suppressions="' + os.path.join(toplevel, "config", "valgrind.sup") + '" "' + exe + '" ') - else: - if exe.find(" ") != -1: - output.write('"' + exe + '" ') - else: - output.write(exe + " ") - - if exe.find("IceUtil\\") != -1 or exe.find("IceUtil/") != -1: - output.write(' ' + options) - else: - output.write(getCommandLineProperties(exe, config, cfgName) + ' ' + options) - - commandline = output.getvalue() - output.close() - - return commandline - -def directoryToPackage(): - """Determine the package name from the directory.""" - base = os.getcwd() - after = [] - lang = getDefaultMapping() - - if "java" in lang: - # Remove Java's extra directory structure from the path while we search it - base = base.replace(os.path.join("src", "main", "java", "test"), '') - - before = base - - while len(before) > 0: - current = os.path.basename(before) - before = os.path.dirname(before) - if current == lang: - break - after.insert(0, current) - else: - raise RuntimeError("cannot find language dir") - return ".".join(after) - -def getDefaultServerFile(baseDir = os.getcwd()): - lang = getDefaultMapping() - if lang in ["cpp", "objective-c", "js", "ruby", "php"]: - return getTestExecutable("server", baseDir) - if lang in ["csharp"]: - return "server" - if lang == "python": - return "Server.py" - if lang == "java" or lang == "java-compat": - pkg = directoryToPackage() - if len(pkg) > 0: - pkg = pkg + "." - return pkg + "Server" - raise RuntimeError("unknown language") - -def getDefaultClientFile(lang = None, baseDir = ""): - if lang is None: - lang = getDefaultMapping() - if lang in ["cpp", "objective-c"]: - return getTestExecutable("client", baseDir) - if lang == "ruby": - return "Client.rb" - if lang == "php": - return "Client.php" - if lang in ["csharp"]: - return "client" - if lang == "python": - return "Client.py" - if lang == "java" or lang == "java-compat": - pkg = directoryToPackage() - if len(pkg) > 0: - pkg = pkg + "." - return pkg + "Client" - if lang == "js": - return "run.js" - raise RuntimeError("unknown language") - -def getDefaultCollocatedFile(): - lang = getDefaultMapping() - if lang in ["cpp", "objective-c"]: - return getTestExecutable("collocated") - if lang == "ruby": - return "Collocated.rb" - if lang == "php": - return "Collocated.php" - if lang in ["csharp"]: - return "collocated" - if lang == "python": - return "Collocated.py" - if lang == "java" or lang == "java-compat": - return directoryToPackage() + ".Collocated" - -import Expect - -def _spawn(cmd, env=None, cwd=None, startReader=True, lang=None): - # Start/Reset the watch dog thread - global watchDog - if watchDog is None: - watchDog = WatchDog() - else: - watchDog.reset() - - if debug: - sys.stdout.write("(%s) " % cmd) - sys.stdout.flush() - if printenv: - dumpenv(env, lang) - - try: - process = Expect.Expect(cmd, startReader=startReader, env=env, logfile=tracefile, cwd=cwd) - except: - print("Command failed:\n" + cmd) - traceback.print_exc(file=sys.stderr) - sys.exit(1) - - return process - -def spawn(cmd, cwd=None): - # Spawn given command with test environment. - return _spawn(cmd, getTestEnv(getDefaultMapping(), os.getcwd())) - -def spawnClient(cmd, env=None, cwd=None, echo=True, startReader=True, lang=None): - client = _spawn(cmd, env, cwd, startReader=startReader, lang=lang) - if echo: - client.trace(clientTraceFilters) - return client - -def spawnServer(cmd, env=None, cwd=None, count=1, adapter=None, echo=True, lang=None, mx=False, timeout=60): - server = _spawn(cmd, env, cwd, lang=lang) - - # Count + 1 if IceMX enabled - if mx: - count = count + 1 - - if adapter: - server.expect("%s ready\n" % adapter, timeout = timeout) - else: - while count > 0: - server.expect("[^\n]+ ready\n", timeout = timeout) - count = count - 1 - if echo: - server.trace([re.compile("[^\n]+ ready")] + serverTraceFilters) - return server - -import subprocess -def runCommand(command): - env = getTestEnv(getDefaultMapping(), os.getcwd()) - - # - # popen3 has problems dealing with white spaces in command line. - # - if isWin32(): - CREATE_NEW_PROCESS_GROUP = 512 - # - # We set shell=True to make sure executables are correctly searched - # in directories specified by the PATH environment variable. - # - p = subprocess.Popen(command, shell=True, bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, creationflags = 512, env = env) - else: - p = subprocess.Popen(command, shell=True, bufsize=1024, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, close_fds=True, env = env) - - return p; - -def matchAppVerifierSuccess(): - return re.escape("\nApplication Verifier ") + ".*\n" + \ - re.escape("Copyright (c) Microsoft Corporation. All rights reserved.") + \ - ".*\n\n$" #After all match to newlines at end. - -def setAppVerifierSettings(targets, cwd=os.getcwd()): - for exe in targets: - if exe.endswith(".exe") == False: - exe += ".exe" - - #First enable all appverifier tests - cmd = "appverif -enable * -for " + exe - verifier = _spawn(cmd, cwd=cwd) - verifier.expect(matchAppVerifierSuccess(), -1) - - #Now disable all tests we are not intested in - cmd = "appverif -disable LuaPriv PrintDriver PrintApi Networking HighVersionLie -for " + exe - verifier = _spawn(cmd, cwd=cwd) - verifier.expectall(["Application Verifier","",""], -1) - -def appVerifierAfterTestEnd(targets, cwd=os.getcwd()): - for exe in targets: - if exe.endswith(".exe") == False: - exe += ".exe" - - # Export appverifier logs to a xml file in cwd - logName = cwd - if logName is None: - logName = os.path.dirname(exe) - logName += "/" + os.path.basename(exe) + "_appverifier_log.xml" - cmd = "appverif -export log -for " + exe + " -with To=" + logName - verifier = _spawn(cmd, cwd=cwd) - verifier.expect(matchAppVerifierSuccess(), -1) - - # Delete appverifier logs from registry - cmd = "appverif -delete logs -for " + exe - verifier = _spawn(cmd, cwd=cwd) - verifier.expect(matchAppVerifierSuccess(), -1) - - # Delete appverifier settings - cmd = "appverif -delete settings -for " + exe - verifier = _spawn(cmd, cwd=cwd) - verifier.expect(matchAppVerifierSuccess(), -1) - -def getMirrorDir(base, mapping): - """Get the mirror directory for the current test in the given mapping.""" - lang = getDefaultMapping() - after = [] - - if lang == "js": - if isWin32(): - base = base.replace("\\es5", "") - else: - base = base.replace("/es5", "") - elif "java" in lang: - # Remove Java's extra directory structure from the path while we search it - base = base.replace(os.path.join("src", "main", "java", "test"), '') - - before = base - while len(before) > 0: - current = os.path.basename(before) - before = os.path.dirname(before) - if current == lang: - break - after.insert(0, current) - else: - raise RuntimeError("cannot find language dir") - - dir = os.path.join(before, mapping) - # Deal with Java's different directory structure - if "java" in mapping: - dir = os.path.join(dir, "test", "src", "main", "java") - return os.path.join(dir, *after) - -def getMappingDir(base, mapping, dirnames): - """Get the directory for the given mapping.""" - lang = getDefaultMapping() - after = [] - before = base - while len(before) > 0: - current = os.path.basename(before) - before = os.path.dirname(before) - if current == lang: - break - after.insert(0, current) - else: - raise RuntimeError("cannot find language dir") - return os.path.join(before, mapping, *dirnames) - -def getClientCrossTestDir(base): - """Get the client directory from client-home for the given test.""" - global clientHome - if not clientHome: - return base - - lang = getDefaultMapping() - after = [] - before = base - while len(before) > 0: - current = os.path.basename(before) - before = os.path.dirname(before) - if current == lang: - break - after.insert(0, current) - else: - raise RuntimeError("cannot find language dir") - return os.path.join(clientHome, lang, *after) - - -def clientServerTest(cfgName = None, additionalServerOptions = "", additionalClientOptions = "", - server = None, client = None, serverenv = None, clientenv = None, - interpreterOptions = ""): - lang = getDefaultMapping() - testdir = os.getcwd() - - # Setup the server. - if lang in ["ruby", "php", "js"]: - serverdir = getMirrorDir(testdir, "cpp") - else: - serverdir = testdir - - if server is None: - server = getDefaultServerFile(serverdir) - elif lang in ["ruby", "php", "js"]: - server = getTestExecutable(server, serverdir) - - if client is None: - client = getDefaultClientFile() - - serverDesc = os.path.basename(server) - clientDesc = os.path.basename(client) - - if lang != "java" and lang != "java-compat": - server = os.path.join(serverdir, server) - - if serverenv is None: - if lang in ["ruby", "php", "js"]: - serverenv = getTestEnv("cpp", serverdir) - else: - serverenv = getTestEnv(lang, serverdir) - - global cross - if len(cross) > 0: - if lang == "js" and cross[0] != lang: - print("** skipping js cross test ") - return - elif len(cross) == 0: - cross.append(lang) - - global controller - global clientHome - for clientLang in cross: - clientCfg = DriverConfig("client") - if clientLang != lang: - if clientDesc != os.path.basename(getDefaultClientFile()): - print("** skipping cross test") - return - - if clientHome: - clientdir = getMirrorDir(getClientCrossTestDir(testdir), clientLang) - else: - clientdir = getMirrorDir(testdir, clientLang) - - client = getDefaultClientFile(clientLang, clientdir) - clientDesc = os.path.basename(client) - clientCfg.lang = clientLang - - if not os.path.exists(clientdir): - print("** no matching test for %s" % clientLang) - return - else: - if clientHome: - clientdir = getClientCrossTestDir(testdir) - else: - clientdir = testdir - if not os.path.exists(clientdir): - print("** no matching test for %s" % clientLang) - return - - if clientLang != "java" and clientLang != "java-compat": - client = os.path.join(clientdir, client) - - if clientenv is None: - clientenv = getTestEnv(clientLang, clientdir) - - clientExe = client - serverExe = server - - if appverifier: - setAppVerifierSettings([clientExe, serverExe]) - if not controller: - sys.stdout.write("starting " + serverDesc + "... ") - sys.stdout.flush() - serverCfg = DriverConfig("server") - if lang in ["ruby", "php", "js"]: - serverCfg.lang = "cpp" - - server = getCommandLine(server, serverCfg, additionalServerOptions, interpreterOptions) - serverProc = spawnServer(server, env = serverenv, lang=serverCfg.lang, mx=serverCfg.mx) - print("ok") - sys.stdout.flush() - - if not serverOnly: - if clientLang == lang: - sys.stdout.write("starting %s... " % clientDesc) - else: - sys.stdout.write("starting %s %s ... " % (clientLang, clientDesc)) - sys.stdout.flush() - if not controller: - cfgName = None - if clientLang == "js" and es5 and client.find("/es5/") == -1: - client = client.replace("test/Ice/", "test/Ice/es5/") - client = client.replace("test/Glacier2/", "test/Glacier2/es5/") - - client = getCommandLine(client, clientCfg, additionalClientOptions, interpreterOptions, cfgName) - clientProc = spawnClient(client, env = clientenv, cwd = clientdir, startReader = False, lang=clientCfg.lang) - print("ok") - - global watchDog - clientProc.startReader(watchDog) - clientProc.waitTestSuccess() - - if not controller: - serverProc.waitTestSuccess() - - if appverifier: - appVerifierAfterTestEnd([clientExe, serverExe]) - -def collocatedTest(additionalOptions = ""): - if controller or serverOnly: - print("** skipping collocated test") - return - lang = getDefaultMapping() - if len(cross) > 0 and cross[0] != lang: - print("** skipping cross test") - return - testdir = os.getcwd() - - collocated = getDefaultCollocatedFile() - if lang != "java" and lang != "java-compat": - collocated = os.path.join(testdir, collocated) - - exe = collocated - if appverifier: - setAppVerifierSettings([exe]) - - env = getTestEnv(lang, testdir) - - sys.stdout.write("starting collocated... ") - sys.stdout.flush() - collocated = getCommandLine(collocated, DriverConfig("colloc"), additionalOptions) - collocatedProc = spawnClient(collocated, env = env, startReader = False, lang=lang) - print("ok") - - global watchDog - collocatedProc.startReader(watchDog) - collocatedProc.waitTestSuccess() - if appverifier: - appVerifierAfterTestEnd([exe]) - -def clientEchoTest(additionalServerOptions = "", additionalClientOptions = "", - server = None, client = None, serverenv = None, clientenv = None): - - lang = getDefaultMapping() - testdir = os.getcwd() - - # Setup the server. - if lang in ["ruby", "php", "js"]: - serverdir = getMappingDir(testdir, "cpp", ["test", "Ice", "echo"]) - else: - serverdir = testdir - - if server is None: - server = getDefaultServerFile(serverdir) - if client is None: - client = getDefaultClientFile() - serverDesc = server - clientDesc = client - - if lang != "java" and lang != "java-compat": - server = os.path.join(serverdir, server) - - if serverenv is None: - if lang in ["ruby", "php", "js"]: - serverenv = getTestEnv("cpp", serverdir) - else: - serverenv = getTestEnv(lang, serverdir) - - global cross - if len(cross) == 0: - cross.append(lang) - - global clientHome - for clientLang in cross: - clientCfg = DriverConfig("client") - if clientLang != lang: - if clientDesc != getDefaultClientFile(): - print("** skipping cross test") - return - - clientCfg.lang = clientLang - client = getDefaultClientFile(clientLang) - if clientHome: - clientdir = getMirrorDir(getClientCrossTestDir(testdir), clientLang) - else: - clientdir = getMirrorDir(testdir, clientLang) - if not os.path.exists(clientdir): - print("** no matching test for %s" % clientLang) - return - else: - if clientHome: - clientdir = getClientCrossTestDir(testdir) - else: - clientdir = testdir - if not os.path.exists(clientdir): - print("** no matching test for %s" % clientLang) - return - - if clientLang != "java" and clientLang != "java-compat": - client = os.path.join(clientdir, client) - - if clientenv is None: - clientenv = getTestEnv(clientLang, clientdir) - - clientExe = client - serverExe = server - - if appverifier: - setAppVerifierSettings([clientExe, serverExe]) - - sys.stdout.write("starting " + serverDesc + "... ") - sys.stdout.flush() - serverCfg = DriverConfig("server") - if lang in ["ruby", "php", "js"]: - serverCfg.lang = "cpp" - server = getCommandLine(server, serverCfg, additionalServerOptions) - serverProc = spawnServer(server, env = serverenv, lang=serverCfg.lang, mx=serverCfg.mx) - print("ok") - sys.stdout.flush() - - if not serverOnly: - if clientLang == lang: - sys.stdout.write("starting %s... " % clientDesc) - else: - sys.stdout.write("starting %s %s ... " % (clientLang, clientDesc)) - sys.stdout.flush() - - if clientLang == "js" and es5 and client.find("/es5/") == -1: - client = client.replace("test/Ice/", "test/Ice/es5/") - - client = getCommandLine(client, clientCfg, additionalClientOptions) - clientProc = spawnClient(client, env = clientenv, startReader = False, lang=clientCfg.lang) - print("ok") - clientProc.startReader() - clientProc.waitTestSuccess() - - serverProc.waitTestSuccess() - - if appverifier: - appVerifierAfterTestEnd([clientExe, serverExe]) - -def cleanDbDir(path): - if os.path.exists(os.path.join(path, "__Freeze", "lock")): - os.remove(os.path.join(path, "__Freeze", "lock")) - if os.path.exists(os.path.join(path, "__Freeze")): - os.rmdir(os.path.join(path, "__Freeze")) - # - # We include __Freeze in this list even though we just removed it - see ICE-5108. - # - ignore = [".gitignore", "DB_CONFIG", "__Freeze"] - for filename in [ os.path.join(path, f) for f in os.listdir(path) if f not in ignore ]: - os.remove(filename) - -def startClient(exe, args = "", config=None, env=None, echo = True, startReader = True, clientConfig = False, iceOptions = None, iceProfile = None): - if config is None: - config = DriverConfig("client") - if env is None: - env = getTestEnv(getDefaultMapping(), os.getcwd()) - interpreterOptions = "" - if config.lang == "php": - interpreterOptions = phpProfileSetup(clientConfig, iceOptions, iceProfile) - - cmd = getCommandLine(exe, config, args, interpreterOptions) - - return spawnClient(cmd, env = env, echo = echo, startReader = startReader, lang=config.lang) - -def startServer(exe, args = "", config = None, env = None, adapter = None, count = 1, echo = True, timeout = 60, - interpreterOptions = ""): - if config is None: - config = DriverConfig("server") - if env is None: - env = getTestEnv(getDefaultMapping(), os.getcwd()) - cmd = getCommandLine(exe, config, args, interpreterOptions) - return spawnServer(cmd, env = env, adapter = adapter, count = count, echo = echo, lang = config.lang, - mx = config.mx, timeout = timeout) - -def startColloc(exe, args, config=None, env=None, interpreterOptions = ""): - exe = quoteArgument(exe) - if config is None: - config = DriverConfig("colloc") - if env is None: - env = getTestEnv(config.lang, testdir) - cmd = getCommandLine(exe, config, args, interpreterOptions) - return spawnClient(cmd, env = env, lang=config.lang) - -def simpleTest(exe = None, options = "", interpreterOptions = ""): - if exe is None: - exe = getDefaultClientFile() - if appverifier: - setAppVerifierSettings([quoteArgument(exe)]) - - testdir = os.getcwd() - - config = DriverConfig("client") - env = getTestEnv(config.lang, testdir) - - sys.stdout.write("starting client... ") - sys.stdout.flush() - command = getCommandLine(exe, config, options, interpreterOptions) - client = spawnClient(command, startReader = False, env = env, lang = config.lang) - print("ok") - client.startReader() - client.waitTestSuccess() - - if appverifier: - appVerifierAfterTestEnd([exe]) - -def createFile(path, lines, enc=None): - if sys.version_info[0] > 2 and enc: - config = open(path, "w", encoding=enc) - else: - config = open(path, "wb") - for l in lines: - config.write("%s\n" % l) - config.close() - -def getCppBinDir(lang = None): - binDir = os.path.join(getIceDir("cpp"), "bin") - - if isWin32(): - binDir = os.path.join(binDir, "x64" if x64 else "Win32", "Debug" if buildMode == "debug" else "Release") - - if isMINGW() and x64: - binDir = os.path.join(binDir, "x64") - if iceHome: - if lang == None: - lang = getDefaultMapping() - if isVC110() and lang != "python": - binDir = os.path.join(binDir, "vc110") - elif isVC140(): - binDir = os.path.join(binDir, "vc140") - if x64: - if isSolaris(): - if isSparc(): - binDir = os.path.join(binDir, "sparcv9") - else: - binDir = os.path.join(binDir, "amd64") - elif isWin32() and lang != "php": - binDir = os.path.join(binDir, "x64") - - return binDir - -def getSliceTranslator(lang = "cpp"): - compiler = "" - if iceHome: - compiler = os.path.join(iceHome, "bin", "slice2%s" % lang) - else: - compiler = os.path.join(getCppBinDir(), ("slice2%s" % lang)) - if isWin32(): - compiler += ".exe" - return compiler - -def getCppLibDir(lang = None): - if isWin32(): - return getCppBinDir(lang) - else: - libDir = os.path.join(getIceDir("cpp"), "lib") - if isUbuntu() or isDebian(): - libDir = os.path.join(libDir, dpkgHostMultiArch()) - elif x64: - if isSolaris(): - if isSparc(): - libDir = os.path.join(libDir, "64") - else: - libDir = os.path.join(libDir, "amd64") - if isLinux(): - libDir = libDir + "64" - return libDir - return None - -def getServiceDir(): - global serviceDir - if serviceDir is None: - if iceHome: - serviceDir = os.path.join(iceHome, "bin") - else: - serviceDir = "C:\\Program Files\ZeroC\Ice-" + iceVersion + "\\bin" - return serviceDir - -def getTestEnv(lang, testdir): - global compact - env = os.environ.copy() - - # - # Jar files from the source of binary distribution - # - iceJARs = ["ice", "glacier2", "freeze", "icebox", "icestorm", "icegrid", "icepatch2", "icediscovery", - "icelocatordiscovery"] - jarSuffix = "-" + ("compat-") if lang == "java-compat" else "" + getIceJsonVersion() + ".jar" - - # First sanitize the environment. - env["CLASSPATH"] = sanitize(os.getenv("CLASSPATH", "")) - - for d in additionalBinDirectories: - addLdPath(d, env) - - # - # Add cpp/test/Common output directory to the env - # - if lang == "cpp": - baseDir = os.path.join(toplevel, "cpp", "test", "Common") - addLdPath(os.path.join(baseDir, getTestDirectory("testcommon", baseDir)), env) - - # Make sure bzip2 can be found by x86 C# builds on x64 platforms - if lang == "csharp" and not x64: - addPathToEnv("PATH", os.path.join(getCppBinDir("csharp"), "x64"), env) - - # Add test directory to env - if lang == "cpp": - addLdPath(os.path.join(testdir), env) - elif lang == "java" or lang == "java-compat": - addClasspath(os.path.join(testToplevel, lang, "lib", "test.jar"), env) - elif lang == "js": - if es5 and testdir.find("/es5/") == -1: - testdir = testdir.replace("test/Ice/", "test/Ice/es5/") - testdir = testdir.replace("test/Glacier2/", "test/Glacier2/es5/") - addPathToEnv("NODE_PATH", os.path.join(testdir), env) - - # NodeJS is always installed locally even when testing against a binary installation - if os.environ.get("USE_BIN_DIST", "no") != "yes": - addPathToEnv("NODE_PATH", os.path.join(getIceDir("js", testdir), "src"), env) - - if isWin32(): - if lang == "java" and javaLibraryPath: - addPathToEnv("PATH", javaLibraryPath, env) - - if lang == "csharp" and not iceHome: - pkgdir = os.path.join(getIceDir("cpp"), "msbuild", "packages") - pkgsubdir = os.path.join("build", "native", "bin", "x64", "Release") - if isVC120(): - addPathToEnv("PATH", os.path.join(pkgdir, "bzip2.v120.1.0.6.4", pkgsubdir), env) - else: - addPathToEnv("PATH", os.path.join(pkgdir, "bzip2.v140.1.0.6.4", pkgsubdir), env) - - # - # If Ice is installed on the system, set the CLASSPATH for Java and - # NODE_PATH for JavaScript - # - if iceHome in ["/usr", "/usr/local"]: - if lang == "java": - javaDir = os.path.join(iceHome, "share", "java") - for jar in iceJARs: - addClasspath(os.path.join(javaDir, jar + jarSuffix), env) - return env # That's it, we're done! - - # - # For Win32 we always need to add the bin dir to the PATH. For - # others we just need to add it for scripting languages that use - # C++ extensions (py, ruby, php) - # - if isWin32(): - if lang == "java": - addLdPath(os.path.join(getIceDir("cpp"), "bin", "x64" if x64 else ""), env) # Add bin for db53_vc100.dll - addLdPath(getCppLibDir(lang), env) - elif isAIX(): - addLdPath(getCppLibDir(lang), env) - elif lang in ["python", "ruby", "php", "js", "objective-c"]: - # C++ binaries use rpath $ORIGIN or similar to find the Ice libraries - addLdPath(getCppLibDir(lang), env) - - if lang == "java": - # The Ice.jar and Freeze.jar comes from the installation - # directory or the toplevel dir. - javaDir = os.path.join(getIceDir("java", testdir), "lib") - for jar in iceJARs: - addClasspath(os.path.join(javaDir, jar + jarSuffix), env) - - # - # On Windows, C# assemblies are found thanks to the .exe.config files. - # - if lang == "csharp": - if compact: - addPathToEnv("DEVPATH", os.path.join(getIceDir("csharp", testdir), "Assemblies", "cf"), env) - elif isWin32(): - addPathToEnv("DEVPATH", os.path.join(getIceDir("csharp", testdir), "Assemblies"), env) - else: - addPathToEnv("MONO_PATH", os.path.join(getIceDir("csharp", testdir), "Assemblies"), env) - - if os.environ.get("USE_BIN_DIST", "no") != "yes": - # - # On Windows x64, set PYTHONPATH to python/x64. - # - if lang == "python": - pythonDir = os.path.join(getIceDir("python", testdir), "python") - if isWin32(): - addPathToEnv("PYTHONPATH", pythonDir, env) - pythonDir = os.path.join(pythonDir, "Win32" if x86 else "x64", "Debug" if buildMode == "debug" else "Release") - addPathToEnv("PYTHONPATH", pythonDir, env) - - # - # If testing with source dist we need to set RUBYLIB - # - if lang == "ruby": - addPathToEnv("RUBYLIB", os.path.join(getIceDir("ruby", testdir), "ruby"), env) - - return env; - -def getTestName(): - lang = getDefaultMapping() - base = os.getcwd() - - if "java" in lang: - # Remove Java's extra directory structure from the path while we search it - base = base.replace(os.path.join("src", "main", "java", "test"), '') - - here = base.split(os.sep) - here.reverse() - for i in range(0, len(here)): - if here[i] == lang: - break - else: - raise RuntimeError("cannot find language dir") - here = here[:i-1] - here.reverse() - # The crossTests list is in UNIX format. - return os.path.join(*here).replace(os.sep, '/') - -def stopWatchDog(): - global watchDog - watchDog.stop() - watchDog.join() - watchDog = None - -def joindog(dog): - dog.stop() - dog.join() - -class WatchDog(threading.Thread): - def __init__(self): - self._resetFlag = False - self._stopFlag = False - self._cv = threading.Condition() - threading.Thread.__init__(self) - - # The thread is marked as a daemon thread. The atexit handler - # joins with the thread on exit. If the thread is not daemon, - # the atexit handler will not be called. - self.setDaemon(True) - self.start() - atexit.register(joindog, self) - - def run(self): - try: - self._cv.acquire() - while True: - self._cv.wait(240) - if self._stopFlag: - break - if self._resetFlag: - self._resetFlag = False - else: - print("\a*** %s Warning: Test has been inactive for 4 minutes and may be hung" % - time.strftime("%x %X")) - self._cv.release() - except: - # - # Exceptions can be raised if the thread is still alive when the interpreter is - # in the process of shutting down. For example, Python resets module objects to None, - # so code such as "time.strftime()" can fail with AttributeError. - # - pass - - def reset(self): - self._cv.acquire() - self._resetFlag = True - self._cv.notify() - self._cv.release() - - def stop(self): - self._cv.acquire() - self._stopFlag = True - self._cv.notify() - self._cv.release() - -def processCmdLine(): - def usage(): - print("usage: " + sys.argv[0] + """ - --debug Display debugging information on each test. - --trace=<file> Display tracing. - --protocol=<prot> Run with the given protocol (tcp|ssl|ws|wss|bt). - --compress Run the tests with protocol compression. - --valgrind Run the tests with valgrind. - --appverifier Run the tests with appverifier. - --host=host Set --Ice.Default.Host=<host>. - --serialize Run with connection serialization. - --ipv6 Use IPv6 addresses. - --socks Use SOCKS proxy running on localhost. - --ice-home=<path> Use the binary distribution from the given path. - --mode=debug|release Run the tests with debug or release mode builds (win32 only)." - --x86 Binary distribution is 32-bit. - --x64 Binary distribution is 64-bit. - --c++11 Binary distribution is c++11. - --es5 Use JavaScript ES5 (Babel compiled code) - --static Binary distribution is static. - --env Print important environment variables. - --cross=lang Run cross language test. - --client-home=<dir> Run cross test clients from the given Ice source distribution. - --service-dir=<dir> Where to locate services for builds without service support. - --compact Ice for .NET uses the Compact Framework. - --winrt Run server with configuration suited for WinRT client. - --server Run only the server. - --mx Enable IceMX when running the tests. - --controller=<host> Use the test controller on the specified host. - --arg=<property> Append the given argument. - """) - sys.exit(2) - - try: - opts, args = getopt.getopt( - sys.argv[1:], "", ["debug", "trace=", "protocol=", "compress", "valgrind", "host=", "serialize", "ipv6", \ - "socks", "ice-home=", "mode=", "x86", "x64", "cross=", "client-home=", "env", \ - "service-dir=", "appverifier", "arg=", \ - "compact", "winrt", "server", "mx", "c++11", "es5", "static", "controller=", "configName="]) - except getopt.GetoptError: - usage() - - if args: - usage() - - global serverOnly - global winrt - global buildMode - for o, a in opts: - if o == "--ice-home": - global iceHome - iceHome = a - elif o == "--mode": - if a not in ( "debug", "release"): - usage() - buildMode = a - elif o == "--cross": - global cross - cross.append(a) - crossLang = ["cpp", "csharp", "java", "java-compat", "js", "php", "python", "ruby", "objective-c"] - if not a in crossLang: - print("cross must be one of %s" % ', '.join(crossLang)) - sys.exit(1) - if getTestName() not in crossTests: - print("*** This test does not support cross language testing") - sys.exit(0) - elif o == "--client-home": - global clientHome - clientHome = a - elif o == "--x64": - global x64 - x64 = True - elif o == "--x86": - global x86 - x86 = True - x64 = False - elif o == "--c++11": - global cpp11 - cpp11 = True - elif o == "--es5": - global es5 - es5 = True - elif o == "--static": - global static - static = True - elif o == "--compress": - global compress - compress = True - elif o == "--serialize": - global serialize - serialize = True - elif o == "--host": - global host - host = a - elif o == "--valgrind": - global valgrind - valgrind = True - elif o == "--appverifier": - if not isWin32() or getDefaultMapping() != "cpp": - print("--appverifier option is only supported for Win32 c++ tests.") - sys.exit(1) - global appverifier - appverifier = True - elif o == "--ipv6": - global ipv6 - ipv6 = True - elif o == "--socks": - global socksProxy - socksProxy = True - if o == "--trace": - global tracefile - if a == "stdout": - tracefile = sys.stdout - else: - tracefile = open(a, "w") - elif o == "--debug": - global debug - debug = True - elif o == "--env": - global printenv - printenv = True - elif o == "--protocol": - if a not in ("bt", "bts", "ws", "wss", "ssl", "tcp"): - usage() - # ssl protocol isn't directly supported with mono. - if mono and getDefaultMapping() == "csharp" and (a == "ssl" or a == "wss"): - print("SSL is not supported with mono") - sys.exit(1) - if a in ["bt", "bts"] and not isLinux(): - print("Bluetooth is only supported on Linux") - sys.exit(1) - global protocol - protocol = a - elif o == "--service-dir": - global serviceDir - serviceDir = a - elif o == "--compact": - global compact - compact = True - elif o == "--winrt": - winrt = True - serverOnly = True - elif o == "--server": - serverOnly = True - elif o == '--arg': - extraArgs.append(a) - elif o == "--mx": - global mx - mx = True - elif o == "--controller": - global controller - controller = a - elif o == "--configName": - global configName - configName = a - if protocol in ["ssl", "wss"] and not serverOnly and getDefaultMapping() == "js": - print("SSL is not supported with Node.js") - sys.exit(1) - - if len(args) > 0: - usage() - - if isWin32() and not buildMode: - print("Error: please define --mode=debug or --mode=release") - sys.exit(1) - - if not os.environ.get("TESTCONTROLLER"): - if iceHome: - sys.stdout.write("*** using Ice installation from " + iceHome + " ") - else: - sys.stdout.write("*** using Ice source dist ") - if armv7l: - sys.stdout.write("(ARMv7)") - elif x64: - sys.stdout.write("(64bit) ") - else: - sys.stdout.write("(32bit) ") - sys.stdout.write("\n") - -def runTests(start, expanded, num = 0, script = False): - total = 0 - for tests in expanded: - for i, args, config in tests: - total = total + 1 - # - # The configs argument is a list containing one or more test configurations. - # - index = 0 - for tests in expanded: - for i, args, config in tests: - index = index + 1 - if index < start: - continue - i = os.path.normpath(i) - - # Deal with Java's different directory structure - if i.find(os.path.join("java","test")) != -1: - dir = os.path.join(testToplevel, "java", "test", "src", "main", i) - elif i.find(os.path.join("java-compat","test")) != -1: - dir = os.path.join(testToplevel, "java-compat", "test", "src", "main", i.replace('-compat','')) - elif es5 and i.find(os.path.join("js","test")) != -1: - dir = os.path.join(testToplevel, i.replace("test/Ice/", "test/Ice/es5/") - .replace("test/Glacier2/", "test/Glacier2/es5/")) - else: - dir = os.path.join(testToplevel, i) - dir = os.path.normpath(dir) - - sys.stdout.write("\n") - if num > 0: - sys.stdout.write("[" + str(num) + "] ") - if script: - prefix = "echo \"" - suffix = "\"" - else: - prefix = "" - suffix = "" - - print("%s*** running tests %d/%d in %s%s" % (prefix, index, total, dir, suffix)) - sys.stdout.write("%s*** configuration: " % prefix) - if len(args.strip()) == 0: - sys.stdout.write("Default ") - else: - sys.stdout.write(args.strip() + " ") - print(suffix) - - if args.find("cross") != -1: - test = os.path.join(*i.split(os.sep)[2:]) - # The crossTests list is in UNIX format. - test = test.replace(os.sep, '/') - if not test in crossTests: - print("%s*** test does not support cross testing%s" % (prefix, suffix)) - continue - - if args.find("es5") != -1 and "noes5" in config: - print("%s*** test not supported with es5%s" % (prefix, suffix)) - continue - - # - # Skip tests not supported with IPv6 if necessary - # - if args.find("ipv6") != -1 and "noipv6" in config: - print("%s*** test not supported with IPv6%s" % (prefix, suffix)) - continue - - if args.find("compress") != -1 and "nocompress" in config: - print("%s*** test not supported with compression%s" % (prefix, suffix)) - continue - - if args.find("socks") != -1 and "nosocks" in config: - print("%s*** test not supported with SOCKS%s" % (prefix, suffix)) - continue - - if args.find("compact") != -1 and \ - ("nocompact" in config or \ - args.find("ssl") != -1 or \ - args.find("compress") != -1): - print("%s*** test not supported with Compact Framework%s" % (prefix, suffix)) - continue - - if args.find("mx") != -1 and "nomx" in config: - print("%s*** test not supported with IceMX enabled%s" % (prefix, suffix)) - continue - - if args.find("compact") == -1 and "compact" in config: - print("%s*** test requires Compact Framework%s" % (prefix, suffix)) - continue - - if isVista() and "novista" in config: - print("%s*** test not supported under Vista%s" % (prefix, suffix)) - continue - - if isDarwin() and "nodarwin" in config: - print("%s*** test not supported under Darwin%s" % (prefix, suffix)) - continue - - if isYocto() and "noyocto" in config: - print("%s*** test not supported under Yocto%s" % (prefix, suffix)) - continue - - if not isWin32() and "win32only" in config: - print("%s*** test only supported under Win32%s" % (prefix, suffix)) - continue - - if isVC100() and "novc100" in config: - print("%s*** test not supported with VC++ 10.0%s" % (prefix, suffix)) - continue - - if cpp11 and "noc++11" in config: - print("%s*** test not supported with C++11%s" % (prefix, suffix)) - continue - - if static and "nostatic" in config: - print("%s*** test not supported with static%s" % (prefix, suffix)) - continue - - if x86 and iceHome and "nomultiarch" in config: - print("%s*** test not supported with x86 in multiarch%s" % (prefix, suffix)) - continue - - if isMINGW() and "nomingw" in config: - print("%s*** test not supported with MINGW%s" % (prefix, suffix)) - continue - - if isWin32() and "nowin32" in config: - print("%s*** test not supported with Win32%s" % (prefix, suffix)) - continue - - # If this is mono and we're running ssl protocol tests - # then skip. This occurs when using --all. - if mono and ("nomono" in config or (i.find(os.path.join("csharp", "test")) != -1 and - (args.find("ssl") != -1 or args.find("wss") != -1))): - print("%s*** test not supported with mono%s" % (prefix, suffix)) - continue - - # - # Skip configurations not supported by node - # - if (i.find(os.path.join("js","test")) != -1 and - ((not serverOnly and (args.find("ssl") != -1 or - args.find("wss") != -1 or - args.find("ws") != -1)) or - args.find("compress") != -1 or - args.find("mx") != -1)): - print("%s*** test not supported with Node.js%s" % (prefix, suffix)) - continue - - if (args.find("ssl") != -1 or args.find("wss") != -1) and ("nossl" in config): - print("%s*** test not supported with IceSSL%s" % (prefix, suffix)) - continue - - if (args.find("bt") != -1 or args.find("bts") != -1) and ("bt" not in config): - print("%s*** test not supported with Bluetooth%s" % (prefix, suffix)) - continue - - if (args.find("ws") != -1 or args.find("wss") != -1) and ("nows" in config): - print("%s*** test not supported with IceWS%s" % (prefix, suffix)) - continue - - # If this is java and we're running ipv6 under windows then skip. - if isWin32() and i.find(os.path.join("java","test")) != -1 and args.find("ipv6") != -1 and \ - getJdkVersion().find("java version \"1.6") != -1: - print("%s*** test not supported under windows%s" % (prefix, suffix)) - continue - - # Skip tests not supported by valgrind - if args.find("valgrind") != -1 and ("novalgrind" in config or args.find("ssl") != -1 or - args.find("wss") != -1): - print("%s*** test not supported with valgrind%s" % (prefix, suffix)) - continue - - # Skip tests not supported by appverifier - if args.find("appverifier") != -1 and ("noappverifier" in config): - print("%s*** test not supported with appverifier%s" % (prefix, suffix)) - continue - - # Skip tests that no not exist for this language mapping - if not os.path.exists(dir): - print("%s*** test does not exist for this language mapping%s" % (prefix, suffix)) - continue - - if script: - print("echo \"*** test started: `date`\"") - print("cd %s" % dir) - else: - print("*** test started: " + time.strftime("%x %X")) - sys.stdout.flush() - os.chdir(dir) - - global keepGoing - if script: - print("if ! %s %s %s; then" % (sys.executable, os.path.join(dir, "run.py"), args)) - print(" echo 'test in %s failed'" % os.path.abspath(dir)) - if not keepGoing: - print(" exit 1") - print("fi") - else: - if isWin32(): - if dir.find(os.path.join("js", "test")) != -1 and es5 and dir.find("\\es5\\") == -1: - dir = dir.replace("test\\Ice\\", "test\\Ice\\es5\\").replace("test\\Glacier2\\", "test\\Glacier2\\es5\\") - else: - if dir.find(os.path.join("js", "test")) != -1 and es5 and dir.find("/es5/") == -1: - dir = dir.replace("test/Ice/", "test/Ice/es5/").replace("test/Glacier2/", "test/Glacier2/es5/") - status = os.system(sys.executable + " " + quoteArgument(os.path.join(dir, "run.py")) + " " + args) - if status: - status = status if isWin32() else (status >> 8) - if(num > 0): - sys.stdout.write("[" + str(num) + "] ") - message = "test in " + os.path.abspath(dir) + " failed with exit status", status, - print(message) - if not keepGoing: - sys.exit(status) - else: - print(" ** Error logged and will be displayed again when suite is completed **") - global testErrors - testErrors.append(message) - -class ClientServerTest: - def __init__(self, cfgName, message, additionalServerOptions, additionalClientOptions, - server, client, serverenv, clientenv, interpreterOptions, localOnly): - if cfgName is None: - cfgName = "default" - self.cfgName = cfgName - self.message = message - self.additionalServerOptions = additionalServerOptions - self.additionalClientOptions = additionalClientOptions - self.server = server - self.client = client - self.serverenv = serverenv - self.clientenv = clientenv - self.interpreterOptions = interpreterOptions - self.localOnly = localOnly - - def getConfigName(self): - return self.cfgName - - def getMessage(self): - return self.message - - def isLocalOnly(self): - return self.localOnly - - def getDefaultMessage(self): - return "Running test with regular server." - - def run(self): - clientServerTest(self.cfgName, self.additionalServerOptions, self.additionalClientOptions, self.server, - self.client, self.serverenv, self.clientenv, self.interpreterOptions) - -def queueClientServerTest(configName = None, message = None, additionalServerOptions = "", - additionalClientOptions = "", server = None, client = None, serverenv = None, - clientenv = None, interpreterOptions = "", localOnly = False): - global queuedTests - queuedTests.append(ClientServerTest(configName, message, additionalServerOptions, additionalClientOptions, server, - client, serverenv, clientenv, interpreterOptions, localOnly)) - -class CollocatedTest: - def __init__(self, message = None, additionalOptions = ""): - self.message = message - self.additionalOptions = additionalOptions - - def getMessage(self): - return self.message - - def isLocalOnly(self): - return True - - def getDefaultMessage(self): - return "Running test with collocated server." - - def run(self): - collocatedTest(self.additionalOptions) - -def queueCollocatedTest(message = None, additionalOptions = ""): - global queuedTests - queuedTests.append(CollocatedTest(message, additionalOptions)) - -def runQueuedTests(): - global queuedTests - global serverOnly - global controller - global configName - - if serverOnly: - name = configName - if not name: - name = "default" - - for t in queuedTests: - if isinstance(t, ClientServerTest) and t.getConfigName() == name: - t.run() - return - - print("no queued test found matching configuration name `" + name + "'") - sys.exit(1) - - tests = [] - for t in queuedTests: - if controller and t.isLocalOnly(): - continue - tests.append(t) - - for t in tests: - msg = t.getMessage() - if msg: - print(msg) - elif len(tests) > 1: - print(t.getDefaultMessage()) - t.run() - -if "ICE_CONFIG" in os.environ: - os.unsetenv("ICE_CONFIG") - -import inspect -frame = inspect.currentframe() -# Move to the top-most frame in the callback. -while frame.f_back is not None: - frame = frame.f_back -if os.path.split(frame.f_code.co_filename)[1] == "run.py": - # If we're not in the test directory, chdir to the correct - # location. - if not os.path.isabs(sys.argv[0]): - d = os.path.join(os.getcwd(), sys.argv[0]) - else: - d = sys.argv[0] - d = os.path.split(d)[0] - if os.path.normpath(d) != os.getcwd(): - os.chdir(d) - processCmdLine() - -def getTestDirectory(name, baseDir = os.getcwd()): - if isWin32(): - buildDir = "msbuild" - platform = "x64" if x64 else "Win32" - if cpp11: - configuration = "Cpp11-Debug" if buildMode == "debug" else "Cpp11-Release" - else: - configuration = "Debug" if buildMode == "debug" else "Release" - else: - buildDir = "build" - if isDarwin(): - platform = "macosx" - elif isUbuntu() or isDebian(): - platform = "x86_64-linux-gnu" if x64 else "i386-linux-gnu" - elif isAIX(): - platform = "ppc64" if x64 else "ppc" - else: - platform = "x64" if x64 else "x86" - configuration = ("cpp11-" if cpp11 else "") + ("static" if static else "shared") - - if os.path.isdir(os.path.join(baseDir, buildDir, name)): - return os.path.join(buildDir, name, platform, configuration) - else: - return os.path.join(buildDir, platform, configuration) - -def getTestExecutable(name, baseDir = os.getcwd()): - return os.path.join(getTestDirectory(name, baseDir), name) - -# -# Used for tests which have Ice as a submodule -# -def setTestToplevel(path): - global testToplevel - testToplevel = path - -# -# Used for Freeze -# -def setJavaLibraryPath(path): - global javaLibraryPath - javaLibraryPath = path diff --git a/scripts/Util.py b/scripts/Util.py new file mode 100644 index 00000000000..17f88cd3771 --- /dev/null +++ b/scripts/Util.py @@ -0,0 +1,2114 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import os, sys, runpy, getopt, traceback, types, threading, time, datetime, re, itertools, random, subprocess, shutil + +isPython2 = sys.version_info[0] == 2 +if isPython2: + import Queue as queue + from StringIO import StringIO +else: + import queue + from io import StringIO + +from collections import OrderedDict +import Expect + +toplevel = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) + +def run(cmd, cwd=None): + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=cwd) + if(p.wait() != 0): + raise RuntimeError(cmd + " failed:\n" + p.stdout.read().strip()) + return p.stdout.read().decode('UTF-8').strip() + +def val(v, escapeQuotes=False, quoteValue=True): + if type(v) == bool: + return "1" if v else "0" + elif type(v) == str: + if not quoteValue or v.find(" ") < 0: + return v + elif escapeQuotes: + return "\\\"{0}\\\"".format(v.replace("\\\"", "\\\\\\\"")) + else: + return "\"{0}\"".format(v) + else: + return str(v) + +def getIceSoVersion(): + config = open(os.path.join(toplevel, "cpp", "include", "IceUtil", "Config.h"), "r") + intVersion = int(re.search("ICE_INT_VERSION ([0-9]*)", config.read()).group(1)) + majorVersion = int(intVersion / 10000) + minorVersion = int(intVersion / 100) - 100 * majorVersion + patchVersion = intVersion % 100 + if patchVersion < 50: + return '%d' % (majorVersion * 10 + minorVersion) + elif patchVersion < 60: + return '%da%d' % (majorVersion * 10 + minorVersion, patchVersion - 50) + else: + return '%db%d' % (majorVersion * 10 + minorVersion, patchVersion - 60) + +class Platform: + + def __init__(self): + self.parseBuildVariables({ + "supported-platforms" : ("supportedPlatforms", lambda s : s.split(" ")), + "supported-configs" : ("supportedConfigs", lambda s : s.split(" ")) + }) + + def parseBuildVariables(self, variables): + # Run make to get the values of the given variables + output = run('make print V="{0}"'.format(" ".join(variables.keys())), cwd = toplevel) + for l in output.split("\n"): + match = re.match(r'^.*:.*: (.*) = (.*)', l) + if match and match.group(1): + if match.group(1) in variables: + (varname, valuefn) = variables[match.group(1).strip()] + value = match.group(2).strip() or "" + setattr(self, varname, valuefn(value) if valuefn else value) + + def getDefaultBuildPlatform(self): + return os.environ.get("PLATFORMS", "").split(" ")[0] or self.supportedPlatforms[0] + + def getDefaultBuildConfig(self): + return os.environ.get("CONFIGS", "").split(" ")[0] or self.supportedConfigs[0] + + def getBinSubDir(self, mapping, current): + # Return the bin sub-directory for the given mapping,platform,config, + # to be overriden by specializations + return "bin" + + def getLibSubDir(self, mapping, current): + # Return the bin sub-directory for the given mapping,platform,config, + # to be overriden by specializations + return "lib" + + def getBuildSubDir(self, name, current): + # Return the build sub-directory, to be overriden by specializations + return os.path.join("build", current.config.buildPlatform, current.config.buildConfig) + + def getLdPathEnvName(self): + return "LD_LIBRARY_PATH" + + def getIceDir(self): + return "/usr" + + def getSliceDir(self, iceDir): + if iceDir.startswith("/usr"): + return os.path.join(iceDir, "share", "ice", "slice") + else: + return os.path.join(iceDir, "slice") + + def getDefaultExe(self, name, config): + if name == "icebox" and config.cpp11: + name += "++11" + return name + + def hasOpenSSL(self): + # This is used by the IceSSL test suite to figure out how to setup certificates + return False + + def canRun(self, current): + return True + +class Darwin(Platform): + + def getDefaultBuildPlatform(self): + return "macosx" + + def getLdPathEnvName(self): + return "DYLD_LIBRARY_PATH" + + def getIceDir(self): + return "/usr/local" + +class AIX(Platform): + + def hasOpenSSL(self): + return True + +class Linux(Platform): + + def __init__(self): + Platform.__init__(self) + self.parseBuildVariables({ + "linux_id" : ("linuxId", None), + "build-platform" : ("buildPlatform", None), + "foreign-platforms" : ("foreignPlatforms", lambda s : s.split(" ") if s else []), + }) + self.multiArch = {} + if self.linuxId in ["ubuntu", "debian"]: + for p in [self.buildPlatform] + self.foreignPlatforms: + self.multiArch[p] = run("dpkg-architecture -f -a{0} -qDEB_HOST_MULTIARCH 2> /dev/null".format(p)) + + def hasOpenSSL(self): + return True + + def getBinSubDir(self, mapping, current): + if self.linuxId in ["ubuntu", "debian"] and current.config.buildPlatform in self.foreignPlatforms: + return os.path.join("bin", self.multiArch[current.config.buildPlatform]) + return "bin" + + def getLibSubDir(self, mapping, current): + if self.linuxId in ["centos", "rhel", "fedora"]: + return "lib64" if current.config.buildPlatform == "x64" else "lib" + elif self.linuxId in ["ubuntu", "debian"]: + return os.path.join("lib", self.multiArch[current.config.buildPlatform]) + return "lib" + + def getBuildSubDir(self, name, current): + if self.linuxId in ["ubuntu", "debian"]: + return os.path.join("build", self.multiArch[current.config.buildPlatform], current.config.buildConfig) + else: + return os.path.join("build", current.config.buildPlatform, current.config.buildConfig) + + def getDefaultExe(self, name, config): + if name == "icebox": + if self.linuxId in ["centos", "rhel", "fedora"] and config.buildPlatform == "x86": + name += "32" # Multilib platform + if config.cpp11: + name += "++11" + return name + + def canRun(self, current): + if self.linuxId in ["centos", "rhel", "fedora"] and current.config.buildPlatform == "x86": + # + # Don't test Glacier2/IceStorm/IceGrid services with multilib platforms. We only + # build services for the native platform. + # + parent = re.match(r'^([\w]*).*', current.testcase.getTestSuite().getId()).group(1) + if parent in ["Glacier2", "IceStorm", "IceGrid"]: + return False + return True + +class Windows(Platform): + + def parseBuildVariables(self, variables): + pass # Nothing to do, we don't support the make build system on Windows + + def getDefaultBuildPlatform(self): + return "Win32" + + def getDefaultBuildConfig(self): + return "Debug" + + def getCompiler(self): + out = run("cl") + if out.find("Version 16.") != -1: + return "v100" + elif out.find("Version 17.") != -1: + return "v110" + elif out.find("Version 18.") != -1: + return "v120" + elif out.find("Version 19.") != -1: + return "v140" + + def getBinSubDir(self, mapping, current): + c = current.config + if isinstance(mapping, CppMapping) or isinstance(mapping, PhpMapping): + return os.path.join("bin", c.buildPlatform, "Debug" if c.buildConfig.find("Debug") >= 0 else "Release") + return "bin" + + def getLibSubDir(self, mapping, current): + c = current.config + if isinstance(mapping, CppMapping): + return os.path.join("bin", c.buildPlatform, "Debug" if c.buildConfig.find("Debug") >= 0 else "Release") + elif isinstance(mapping, PhpMapping): + return os.path.join("lib", c.buildPlatform, "Debug" if c.buildConfig.find("Debug") >= 0 else "Release") + return "lib" + + def getBuildSubDir(self, name, current): + return os.path.join("msbuild", name, current.config.buildPlatform, current.config.buildConfig) + + def getLdPathEnvName(self): + return "PATH" + + def getIceDir(self): + return None + + def canRun(self, current): + # + # On Windows, if testing with a binary distribution, don't test Glacier2/IceStorm services + # with the Debug configurations since we don't provide binaries for them. + # + if current.driver.useBinDist(): + parent = re.match(r'^([\w]*).*', current.testcase.getTestSuite().getId()).group(1) + if parent in ["Glacier2", "IceStorm"] and current.config.buildConfiguration.find("Debug") >= 0: + return False + return True + +platform = None +if sys.platform == "darwin": + platform = Darwin() +elif sys.platform.startswith("aix"): + platform = AIX() +elif sys.platform.startswith("linux") or sys.platform.startswith("gnukfreebsd"): + platform = Linux() +elif sys.platform == "win32" or sys.platform[:6] == "cygwin": + platform = Windows() + +if not platform: + print("can't run on unknown platform `{0}'".format(sys.platform)) + sys.exit(1) + +def parseOptions(obj, options, mapped={}): + # Transform configuration options provided on the command line to + # object data members. The data members must be already set on the + # object and with the correct type. + obj.parsedOptions=[] + remaining = [] + for (o, a) in options: + if o.startswith("--"): o = o[2:] + if o.startswith("-"): o = o[1:] + if o in mapped: + o = mapped[o] + + if hasattr(obj, o): + if isinstance(getattr(obj, o), bool): + setattr(obj, o, a.lower() in ("yes", "true", "1") if a else True) + elif isinstance(getattr(obj, o), list): + l = getattr(obj, o) + l.append(a) + else: + if not a and not isinstance(a, str): + a = "0" + setattr(obj, o, type(getattr(obj, o))(a)) + obj.parsedOptions.append(o) + else: + remaining.append((o, a)) + options[:] = remaining + + +class Mapping: + + mappings = OrderedDict() + + class Config: + + supportedOptions = ["protocol", "compress", "ipv6", "serialize", "mx"] + + # All option values for Ice/IceBox tests. + coreOptions = { + "protocol" : ["tcp", "ssl", "wss", "ws"], + "compress" : [False, True], + "ipv6" : [False, True], + "serialize" : [False, True], + "mx" : [False, True], + } + + # All option values for IceGrid/IceStorm/Glacier2/IceDiscovery tests. + serviceOptions = { + "protocol" : ["tcp", "wss"], + "compress" : [False, True], + "ipv6" : [False, True], + "serialize" : [False, True], + "mx" : [False, True], + } + + @classmethod + def getOptions(self): + return ("", ["config=", "platform=", "protocol=", "compress", "ipv6", "serialize", "mx", "cprops=", "sprops="]) + + @classmethod + def usage(self): + pass + + @classmethod + def commonUsage(self): + print("") + print("Mapping options:") + print("--protocol=<prot> Run with the given protocol.") + print("--compress Run the tests with protocol compression.") + print("--ipv6 Use IPv6 addresses.") + print("--serialize Run with connection serialization.") + print("--mx Run with metrics enabled.") + print("--cprops=<properties> Specifies a list of additional client properties.") + print("--sprops=<properties> Specifies a list of additional server properties.") + print("--config=<config> Build configuration for native executables.") + print("--platform=<platform> Build plaform for native executables.") + + def __init__(self, options=[]): + self.buildConfig = platform.getDefaultBuildConfig() + self.buildPlatform = platform.getDefaultBuildPlatform() + self.protocol = "tcp" + self.compress = False + self.serialize = False + self.ipv6 = False + self.mx = False + self.cprops = [] + self.sprops = [] + parseOptions(self, options, { "config" : "buildConfig", "platform" : "buildPlatform" }) + + def __str__(self): + s = [] + for o in self.parsedOptions: + v = getattr(self, o) + if v: s.append(o if type(v) == bool else str(v)) + return ",".join(s) + + def getAll(self, current, testcase, rand=False): + + # + # A generator to generate combinations of options (e.g.: tcp/compress/mx, ssl/ipv6/serialize, etc) + # + def gen(supportedOptions): + + if not supportedOptions: + yield self + return + + supportedOptions = supportedOptions.copy() + supportedOptions.update(testcase.getMapping().getOptions()) + supportedOptions.update(testcase.getTestSuite().getOptions()) + supportedOptions.update(testcase.getOptions()) + + for o in self.parsedOptions: + # Remove options which were explicitly set + if o in supportedOptions: + del supportedOptions[o] + + if len(supportedOptions) == 0: + yield self + return + + # Find the option with the longest list of values + length = max([len(v) for v in supportedOptions.values()]) + + # Replace the values with a cycle iterator on the values + for (k, v) in supportedOptions.items(): + supportedOptions[k] = itertools.cycle(random.sample(v, len(v)) if rand else v) + + # Now, for the length of the longuest array of values, we return + # an array with the supported option combinations + for i in range(0, length): + options = [] + for k, v in supportedOptions.items(): + v = next(v) + if v: + if type(v) == bool: + options.append(("--{0}".format(k), None)) + else: + options.append(("--{0}".format(k), v)) + + # Add parsed options + for o in self.parsedOptions: + v = getattr(self, o) + if type(v) == bool: + options.append(("--{0}".format(o), None)) + elif type(v) == list: + options += [("--{0}".format(o), e) for e in v] + else: + options.append(("--{0}".format(o), v)) + + yield self.__class__(options) + + options = None + parent = re.match(r'^([\w]*).*', testcase.getTestSuite().getId()).group(1) + if isinstance(testcase, ClientServerTestCase) and parent in ["Ice", "IceBox"]: + options = current.driver.filterOptions(testcase, self.coreOptions) + elif parent in ["IceGrid", "Glacier2", "IceStorm", "IceDiscovery"]: + options = current.driver.filterOptions(testcase, self.serviceOptions) + + return [c for c in gen(options)] + + def canRun(self, current): + if not platform.canRun(current): + return False + + options = {} + options.update(current.testcase.getTestSuite().getOptions()) + options.update(current.testcase.getOptions()) + for (k, v) in options.items(): + if not hasattr(self, k): + print("warning: unknown option `{0}' specified in `{1}'".format(k, current.testcase)) + continue + if not getattr(self, k) in v: + return False + else: + return True + + def getArgs(self, process, current): + return [] + + def getProps(self, process, current): + props = {} + if isinstance(process, IceProcess): + props["Ice.Warn.Connections"] = True + if self.protocol: + props["Ice.Default.Protocol"] = self.protocol + if self.compress: + props["Ice.Override.Compress"] = "1" + if self.serialize: + props["Ice.ThreadPool.Server.Serialize"] = "1" + if self.ipv6: + props.update({"Ice.IPv6": True, "Ice.PreferIPv6Address": True}) + if self.mx: + props["Ice.Admin.Endpoints"] = "default -h localhost" + props["Ice.Admin.InstanceName"] = "Server" if isinstance(process, Server) else "Client" + props["IceMX.Metrics.Debug.GroupBy"] ="id" + props["IceMX.Metrics.Parent.GroupBy"] = "parent" + props["IceMX.Metrics.All.GroupBy"] = "none" + + # Additional properties specified on the command line with --cprops or --sprops + additionalProps = [] + if self.cprops and isinstance(process, Client): + additionalProps = self.cprops + elif self.sprops and isinstance(process, Server): + additionalProps = self.sprops + for pps in additionalProps: + for p in pps.split(" "): + if p.find("=") > 0: + (k , v) = p.split("=") + props[k] = v + else: + props[p] = True + + return props + + @classmethod + def getByName(self, name): + if not name in self.mappings: + raise RuntimeError("unknown mapping `{0}'".format(name)) + return self.mappings.get(name) + + @classmethod + def getByPath(self, path): + path = os.path.abspath(path) + for m in self.mappings.values(): + if path.startswith(m.getPath()): + return m + + @classmethod + def add(self, name, mapping): + self.mappings[name] = mapping.init(name) + + @classmethod + def getAll(self): + languages = os.environ.get("LANGUAGES", None) + return [self.getByName(l) for l in languages.split(" ")] if languages else self.mappings.values() + + def __init__(self, path=None): + self.platform = None + self.name = None + self.path = os.path.abspath(path) if path else None + self.testsuites = {} + + def init(self, name): + self.name = name + if not self.path: + self.path = os.path.join(toplevel, name) + return self + + def __str__(self): + return self.name + + def createConfig(self, options): + return Mapping.Config(options) + + def filterTestSuite(self, testId, filters, rfilters): + for f in filters: + if not f.search(self.name + "/" + testId): + return True + else: + for f in rfilters: + if f.search(self.name + "/" + testId): + return True + return False + + def loadTestSuites(self, tests, filters=[], rfilters=[]): + for test in tests or [""]: + for root, dirs, files in os.walk(os.path.join(self.getTestsPath(), test)): + + testId = root[len(self.getTestsPath()) + 1:] + if os.sep != "/": + testId = testId.replace(os.sep, "/") + + if self.filterTestSuite(testId, filters, rfilters): + continue + + # + # First check if there's a test.py file in the directory, if there's one use it. + # + if "test.py" in files: + # + # WORKAROUND for Python issue 15230 (fixed in 3.2) where run_path doesn't work correctly. + # + #runpy.run_path(os.path.join(root, "test.py")) + origsyspath = sys.path + sys.path = [root] + sys.path + runpy.run_module("test", init_globals=globals(), run_name=root) + origsyspath = sys.path + continue + + # + # If there's no test.py file in the test directory, we check if there's a common + # script for the test in scripts/tests. If there's on we use it. + # + script = os.path.join(self.getCommonTestsPath(), testId + ".py") + if os.path.isfile(script): + runpy.run_module("tests." + testId.replace("/", "."), init_globals=globals(), run_name=root) + continue + + # + # Finally, we try to "discover/compute" the test by looking up for well-known + # files. + # + testcases = self.computeTestCases(testId, files) + if testcases: + TestSuite(root, testcases) + + def getTestSuites(self): + return self.testsuites.values() + + def addTestSuite(self, testsuite): + assert len(testsuite.path) > len(self.getTestsPath()) + 1 + testSuiteId = testsuite.path[len(self.getTestsPath()) + 1:] + self.testsuites[testSuiteId] = testsuite + return testSuiteId + + def findTestSuite(self, testsuite): + return self.testsuites.get(testsuite if isinstance(testsuite, str) else testsuite.id) + + def computeTestCases(self, testId, files): + + # Instantiate a new test suite if the directory contains well-known source files. + + def checkFile(f, m): + try: + # If given mapping is same as local mapping, just check the files set, otherwise check + # with the mapping + return (self.getDefaultSource(f) in files) if m == self else m.hasSource(testId, f) + except KeyError: + # Expected if the mapping doesn't support the process type (such as clientBidir) + return False + + checkClient = lambda f: checkFile(f, self.getClientMapping()) + checkServer = lambda f: checkFile(f, self.getServerMapping()) + + testcases = [] + if checkClient("client") and checkServer("server"): + testcases.append(ClientServerTestCase()) + if checkClient("client") and checkServer("serveramd") and self.getServerMapping() == self: + testcases.append(ClientAMDServerTestCase()) + if checkClient("client") and len(testcases) == 0: + testcases.append(ClientTestCase()) + if checkClient("collocated"): + testcases.append(CollocatedTestCase()) + if checkClient("clientBidir") and self.getServerMapping().hasSource("Ice/echo", "server"): + testcases.append(ClientEchoServerTestCase()) + if len(testcases) > 0: + return testcases + + def hasSource(self, testId, processType): + try: + return os.path.exists(os.path.join(self.getTestsPath(), testId, self.getDefaultSource(processType))) + except KeyError: + return False + + def getPath(self): + return self.path + + def getTestsPath(self): + return os.path.join(self.path, "test") + + def getCommonTestsPath(self): + return os.path.join(self.path, "..", "scripts", "tests") + + def getTestCwd(self, current): + return current.testcase.getPath() + + def getDefaultSource(self, processType): + return processType + + def getDefaultProcess(self, processType, testsuite): + # + # If no server or client is explictily set with a testcase, getDefaultProcess is called + # to figure out which process class to instantiate. Based on the processType and the testsuite + # we instantiate the right default process class. + # + if processType is None: + return None + elif testsuite.getId().startswith("IceUtil") or testsuite.getId().startswith("Slice"): + return SimpleClient() + elif testsuite.getId().startswith("IceGrid"): + if processType in ["client", "collocated"]: + return IceGridClient() + if processType in ["server", "serveramd"]: + return IceGridServer() + else: + return Server() if processType in ["server", "serveramd"] else Client() + + def getDefaultExe(self, processType, config): + return processType + + def getClientMapping(self): + # The client mapping is always the same as this mapping. + return self + + def getServerMapping(self): + # Can be overriden for client-only mapping that relies on another mapping for servers + return self + + def getBinDir(self, current): + return os.path.join(current.driver.getIceDir(self), platform.getBinSubDir(self, current)) + + def getLibDir(self, current): + return os.path.join(current.driver.getIceDir(self), platform.getLibSubDir(self, current)) + + def getBuildDir(self, name, current): + return platform.getBuildSubDir(name, current) + + def getCommandLine(self, current, process, exe): + name = exe + if isinstance(platform, Windows) and not exe.endswith(".exe"): + exe += ".exe" + if process.isFromBinDir(): + # If it's a process from the bin directory, the location is platform specific + # so we check with the platform. + return os.path.join(self.getBinDir(current), exe) + elif current.testcase: + # If it's a process from a testcase, the binary is in the test build directory. + return os.path.join(current.testcase.getPath(), current.getBuildDir(name), exe) + else: + return exe + + def getProps(self, process, current): + props = {} + if isinstance(process, IceProcess): + if current.config.protocol in ["bt", "bts"]: + props["Ice.Plugin.IceBT"] = self.getPluginEntryPoint("IceBT") + if current.config.protocol in ["ssl", "wss", "bts", "iaps"]: + props.update(self.getSSLProps(process, current.config.protocol)) + return props + + def getSSLProps(self, process, protocol="ssl"): + return { "Ice.Plugin.IceSSL" : self.getPluginEntryPoint("IceSSL") } + + def getArgs(self, process, current): + return [] + + def getEnv(self, process, current): + return {} + + def getOptions(self): + return {} + + def getRunOrder(self): + return ["Slice", "IceUtil", "Ice", "IceSSL", "IceBox", "Glacier2", "IceGrid", "IceStorm"] + + def getCrossTestSuites(self): + return [ + "Ice/ami", + "Ice/info", + "Ice/exceptions", + "Ice/enums", + "Ice/facets", + "Ice/inheritance", + "Ice/invoke", + "Ice/objects", + "Ice/operations", + "Ice/proxy", + "Ice/servantLocator", + "Ice/slicing/exceptions", + "Ice/slicing/objects", + "Ice/optional" + ] + +# +# A Runnable can be used as a "client" for in test cases, it provides +# implements run, setup and teardown methods. +# +class Runnable: + + def __init__(self, desc=None): + self.desc = desc + + def setup(self, current): + ### Only called when ran from testcase + pass + + def teardown(self, current, success): + ### Only called when ran from testcase + pass + + def run(self, current): + pass + +# +# A Process describes how to run an executable process. +# +class Process(Runnable): + + processType = None + + def __init__(self, exe=None, outfilters=[], quiet=False, args=[], props={}, envs={}, desc=None, mapping=None): + Runnable.__init__(self, desc) + self.exe = exe + self.outfilters = outfilters + self.quiet = quiet + self.args = args + self.props = props + self.envs = envs + self.process = None + self.mapping = mapping + + def __str__(self): + if not self.exe: + return str(self.__class__) + return self.exe + (" ({0})".format(self.desc) if self.desc else "") + + def getOutput(self): + assert(self.process) + + def d(s): + return s if isPython2 else s.decode("utf-8") if isinstance(s, bytes) else s + + output = d(self.process.getOutput()) + try: + # Apply outfilters to the output + if len(self.outfilters) > 0: + lines = output.split('\n') + newLines = [] + previous = "" + for line in [line + '\n' for line in lines]: + for f in self.outfilters: + if isinstance(f, types.LambdaType) or isinstance(f, types.FunctionType): + line = f(line) + elif f.search(line): + break + else: + if line.endswith('\n'): + if previous: + newLines.append(previous + line) + previous = "" + else: + newLines.append(line) + else: + previous += line + output = "".join(newLines) + output = output.strip() + return output + '\n' if output else "" + except Exception as ex: + print("unexpected exception while filtering process output:\n" + str(ex)) + raise + + def run(self, current, args=[], props={}, exitstatus=0, timeout=120): + class WatchDog: + + def __init__(self): + self.lastProgressTime = time.time() + self.lock = threading.Lock() + + def reset(self): + with self.lock: self.lastProgressTime = time.time() + + def lastProgress(self): + with self.lock: return self.lastProgressTime + + watchDog = WatchDog() + self.start(current, args, props, watchDog=watchDog) + if not self.quiet and not current.driver.isWorkerThread(): + # Print out the process output to stdout if we're running the client form the main thread. + self.process.trace(self.outfilters) + + try: + while True: + try: + self.process.waitSuccess(exitstatus=exitstatus, timeout=30) + break + except Expect.TIMEOUT: + if time.time() - watchDog.lastProgress() >= timeout: # If no progress, raise + raise + finally: + self.process.terminate() + # Write the output to the test case (but not on stdout) + if not self.quiet: + current.write(self.getOutput(), stdout=False) + + def getEffectiveArgs(self, current, args): + allArgs = [] + allArgs += current.driver.getArgs(self, current) + allArgs += current.config.getArgs(self, current) + allArgs += self.getMapping(current).getArgs(self, current) + allArgs += current.testcase.getArgs(self, current) + allArgs += self.getArgs(current) + allArgs += self.args(self, current) if callable(self.args) else self.args + allArgs += args + allArgs = [a.encode("utf-8") if type(a) == "unicode" else str(a) for a in allArgs] + return allArgs + + def getEffectiveProps(self, current, props): + allProps = {} + allProps.update(current.driver.getProps(self, current)) + allProps.update(current.config.getProps(self, current)) + allProps.update(self.getMapping(current).getProps(self, current)) + allProps.update(current.testcase.getProps(self, current)) + allProps.update(self.getProps(current)) + allProps.update(self.props(self, current) if callable(self.props) else self.props) + allProps.update(props) + return allProps + + def getEffectiveEnv(self, current): + allEnvs = {} + allEnvs.update(self.getMapping(current).getEnv(self, current)) + allEnvs.update(current.testcase.getEnv(self, current)) + allEnvs.update(self.getEnv(current)) + allEnvs.update(self.envs(self, current) if callable(self.envs) else self.envs) + return allEnvs + + def start(self, current, args=[], props={}, watchDog=None): + allArgs = self.getEffectiveArgs(current, args) + allProps = self.getEffectiveProps(current, props) + allEnvs = self.getEffectiveEnv(current) + + # Evaluate and transform properties into command line arguments + allArgs = ["--{0}={1}".format(k, val(v)) for k,v in allProps.items()] + [val(a) for a in allArgs] + + # Evaluate environment values + for k, v in allEnvs.items(): + allEnvs[k] = val(v, quoteValue=False) + + # Get command line from the mapping + cmd = self.getCommandLine(current) + if len(allArgs) > 0: + cmd += " " + " ".join(allArgs) + + # + # Props and arguments can use the format parameters set below in the kargs + # dictionary. It's time to convert them to their values. + # + kargs = { + "process": self, + "testcase": current.testcase, + "testdir": current.testcase.getPath(), + "icedir" : current.driver.getIceDir(current.testcase.getMapping()), + } + cmd = cmd.format(**kargs) + + if current.driver.debug: + if len(allEnvs) > 0: + current.writeln("({0} env={1})".format(cmd, allEnvs)) + else: + current.writeln("({0})".format(cmd)) + + env = os.environ.copy() + env.update(allEnvs) + + cwd = self.getMapping(current).getTestCwd(current) + + self.process = Expect.Expect(cmd, startReader=False, env=env, cwd=cwd, desc=self.desc) + self.process.startReader(watchDog) + try: + self.waitForStart(current) + except: + self.stop(current) + raise + + def waitForStart(self, current): + # To be overriden in specialization to wait for a token indiciating the process readyness. + pass + + def stop(self, current, waitSuccess=False): + if self.process: + try: + if waitSuccess: # Wait for the process to exit successfully by itself. + self.process.waitSuccess(timeout=60) + finally: + self.process.terminate() + if not self.quiet: # Write the output to the test case (but not on stdout) + current.write(self.getOutput(), stdout=False) + self.process = None + + def expect(self, pattern, timeout=60): + assert(self.process) + return self.process.expect(pattern, timeout) + + def sendline(self, data): + assert(self.process) + return self.process.sendline(data) + + def isStarted(self): + return self.process is not None + + def isFromBinDir(self): + return False + + def getArgs(self, current): + return [] + + def getProps(self, current): + return {} + + def getEnv(self, current): + return {} + + def getMapping(self, current): + return self.mapping or current.testcase.getMapping() + + def getExe(self, current): + processType = self.processType or current.testcase.getProcessType(self) + return self.exe or self.getMapping(current).getDefaultExe(processType, current.config) + + def getCommandLine(self, current): + return self.getMapping(current).getCommandLine(current, self, self.getExe(current)) + +# +# A simple client (used to run Slice/IceUtil clients for example) +# +class SimpleClient(Process): + pass + +# +# An IceProcess specialization class. This is used by drivers to figure out if +# the process accepts Ice configuration properties. +# +class IceProcess(Process): + pass + +# +# An Ice server process. It's possible to configure when the server is considered +# ready by setting readyCount or ready. The start method will only return once +# the server is considered "ready". It can also be configure to wait (the default) +# or not wait for shutdown when the stop method is invoked. +# +class Server(IceProcess): + + def __init__(self, exe=None, waitForShutdown=True, readyCount=1, ready=None, startTimeout=60, *args, **kargs): + IceProcess.__init__(self, exe, *args, **kargs) + self.waitForShutdown = waitForShutdown + self.readyCount = readyCount + self.ready = ready + self.startTimeout = startTimeout + + def getProps(self, current): + props = IceProcess.getProps(self, current) + props.update({ + "Ice.ThreadPool.Server.Size": 1, + "Ice.ThreadPool.Server.SizeMax": 3, + "Ice.ThreadPool.Server.SizeWarn": 0, + }) + if self.ready or (self.readyCount + (1 if current.config.mx else 0)) > 0: + props["Ice.PrintAdapterReady"] = 1 + return props + + def waitForStart(self, current): + if self.ready: + self.process.expect("%s ready\n" % self.ready, timeout = self.startTimeout) + else: + count = self.readyCount + (1 if current.config.mx else 0) + while count > 0: + self.process.expect("[^\n]+ ready\n", timeout = self.startTimeout) + count -= 1 + + # Filter out remaining ready messages + self.outfilters.append(re.compile("[^\n]+ ready")) + + # If we are not asked to be quiet and running from the main thread, print the server output + if not self.quiet and not current.driver.isWorkerThread(): + self.process.trace(self.outfilters) + + def stop(self, current, waitSuccess=False): + IceProcess.stop(self, current, waitSuccess and self.waitForShutdown) + +# +# An Ice client process. +# +class Client(IceProcess): + pass + +# +# Executables for processes inheriting this marker class are looked up in the +# Ice distribution bin directory. +# +class ProcessFromBinDir: + + def isFromBinDir(self): + return True + +class SliceTranslator(ProcessFromBinDir, SimpleClient): + + def __init__(self, translator): + SimpleClient.__init__(self, exe=translator, quiet=True, mapping=Mapping.getByName("cpp")) + + def getCommandLine(self, current): + translator = self.getMapping(current).getCommandLine(current, self, self.getExe(current)) + + # + # Look for slice2py installed by Pip if not found in the bin directory + # + if self.exe == "slice2py" and not os.path.exists(translator): + if isinstance(platform, Windows): + return os.path.join(os.path.dirname(sys.executable), "Scripts", "slice2py.exe") + elif os.path.exists("/usr/local/bin/slice2py"): + return "/usr/local/bin/slice2py" + else: + import slice2py + return sys.executable + " " + os.path.normpath( + os.path.join(slice2py.__file__, "..", "..", "..", "..", "bin", "slice2py")) + + return translator + +# +# A test case is composed of servers and clients. When run, all servers are started +# sequentially. When the servers are ready, the clients are also ran sequentially. +# Once all the clients are terminated, the servers are stopped (which waits for the +# successful completion of the server). +# +# A TestCase is also a "Runnable", like the Process class. In other words, it can be +# used a client to allow nested test cases. +# +class TestCase(Runnable): + + def __init__(self, name, client=None, clients=None, server=None, servers=None, args=[], props={}, envs={}, + options={}, desc=None): + Runnable.__init__(self, desc) + + self.name = name + self.parent = None + self.mapping = None + self.testsuite = None + self.options = options + self.dirs = [] + self.files = [] + self.args = args + self.props = props + self.envs = envs + + # + # Setup client list, "client" can be a string in which case it's assumed to + # to the client executable name. + # + self.clients = clients + if client: + client = Client(exe=client) if isinstance(client, str) else client + self.clients = [client] if not self.clients else self.clients + [client] + + # + # Setup server list, "server" can be a string in which case it's assumed to + # to the server executable name. + # + self.servers = servers + if server: + server = Server(exe=server) if isinstance(server, str) else server + self.servers = [server] if not self.servers else self.servers + [server] + + def __str__(self): + return self.name + + def init(self, mapping, testsuite): + # init is called when the testcase is added to the given testsuite + self.mapping = mapping + self.testsuite = testsuite + + # + # If no clients are explicitly specified, we instantiate one if getClientType() + # returns the type of client to instantiate (client, collocated, etc) + # + if not self.clients: + client = self.mapping.getDefaultProcess(self.getClientType(), testsuite) + self.clients = [client] if client else [] + + # + # If no servers are explicitly specified, we instantiate one if getServerType() + # returns the type of server to instantiate (server, serveramd, etc) + # + if not self.servers: + server = self.mapping.getDefaultProcess(self.getServerType(), testsuite) + self.servers = [server] if server else [] + + def getOptions(self): + return self.options + + def setupServerSide(self, current): + # Can be overriden to perform setup activities before the server side is started + pass + + def teardownServerSide(self, current, success): + # Can be overriden to perform terddown after the server side is stopped + pass + + def setupClientSide(self, current): + # Can be overriden to perform setup activities before the client side is started + pass + + def teardownClientSide(self, current, success): + # Can be overriden to perform terddown after the client side is stopped + pass + + def startServerSide(self, current): + for server in self.servers: + self._startServer(current, server) + + def stopServerSide(self, current, success): + for server in reversed(self.servers): + self._stopServer(current, server, success) + + def runClientSide(self, current): + for client in self.clients: + self._runClient(current, client) + + def getTestSuite(self): + return self.testsuite + + def getParent(self): + return self.parent + + def getName(self): + return self.name + + def getPath(self): + return self.testsuite.getPath() + + def getMapping(self): + return self.mapping + + def getArgs(self, process, current): + return self.args + + def getProps(self, process, current): + return self.props + + def getEnv(self, process, current): + return self.envs + + def getProcessType(self, process): + if process in self.clients: + return self.getClientType() + elif process in self.servers: + return self.getServerType() + elif isinstance(process, Server): + return self.getServerType() + else: + return self.getClientType() + + def getClientType(self): + # Overriden by test case specialization to specify the type of client to instantiate + # if no client is explictly provided + return None + + def getServerType(self): + # Overriden by test case specialization to specify the type of client to instantiate + # if no server is explictly provided + return None + + def getServerTestCase(self, cross=None): + testsuite = (cross or self.mapping.getServerMapping()).findTestSuite(self.testsuite) + return testsuite.findTestCase(self) if testsuite else None + + def getClientTestCase(self): + testsuite = self.mapping.getClientMapping().findTestSuite(self.testsuite) + return testsuite.findTestCase(self) if testsuite else None + + def _startServerSide(self, current): + current.push(self) + self.setupServerSide(current) + try: + self.startServerSide(current) + except: + self._stopServerSide(current, False) + raise + finally: + current.pop() + + def _stopServerSide(self, current, success): + current.push(self) + try: + self.stopServerSide(current, success) + finally: + for server in reversed(self.servers): + if server.isStarted(): + self._stopServer(current, server, False) + self.teardownServerSide(current, success) + current.pop() + + def _startServer(self, current, server): + if server.desc: + current.write("starting {0}... ".format(server.desc)) + server.setup(current) + server.start(current) + if server.desc: + current.writeln("ok") + + def _stopServer(self, current, server, success): + try: + server.stop(current, success) + except: + success = False + raise + finally: + server.teardown(current, success) + + def _runClientSide(self, current): + current.push(self) + self.setupClientSide(current) + success = False + try: + self.runClientSide(current) + success = True + finally: + self.teardownClientSide(current, success) + current.pop() + + def _runClient(self, current, client): + success = False + if client.desc: + current.writeln("running {0}...".format(client.desc)) + client.setup(current) + try: + client.run(current) + success = True + finally: + client.teardown(current, success) + + def run(self, current): + try: + current.push(self) + current.result.started(self) + self.runWithDriver(current) + current.result.succeeded(self) + except Exception as ex: + current.result.failed(self, traceback.format_exc() if current.driver.debug else str(ex)) + raise + finally: + current.pop() + for d in self.dirs: + if os.path.exists(d): shutil.rmtree(d) + for f in self.files: + if os.path.exists(f): os.unlink(f) + + def createFile(self, path, lines, encoding=None): + path = os.path.join(self.getPath(), path.decode("utf-8") if isPython2 else path) + with open(path, "w", encoding=encoding) if not isPython2 and encoding else open(path, "wb") as file: + for l in lines: + file.write("%s\n" % l) + self.files.append(path) + + def mkdirs(self, dirs): + for d in dirs if isinstance(dirs, list) else [dirs]: + d = os.path.join(self.getPath(), d) + self.dirs.append(d) + if not os.path.exists(d): + os.makedirs(d) + +class ClientTestCase(TestCase): + + def __init__(self, name="client", *args, **kargs): + TestCase.__init__(self, name, *args, **kargs) + + def runWithDriver(self, current): + current.driver.runTestCase(current) + + def getClientType(self): + return "client" + +class ClientServerTestCase(ClientTestCase): + + def __init__(self, name="client/server", *args, **kargs): + TestCase.__init__(self, name, *args, **kargs) + + def runWithDriver(self, current): + current.driver.runClientServerTestCase(current) + + def getServerType(self): + return "server" + +class ClientEchoServerTestCase(ClientServerTestCase): + + def __init__(self, name="client/echo server", *args, **kargs): + ClientServerTestCase.__init__(self, name, *args, **kargs) + + def getServerTestCase(self, cross=None): + return Mapping.getByName("cpp").findTestSuite("Ice/echo").findTestCase("server") + + def getClientType(self): + return "clientBidir" + +class CollocatedTestCase(ClientTestCase): + + def __init__(self, name="collocated", *args, **kargs): + TestCase.__init__(self, name, *args, **kargs) + + def getClientType(self): + return "collocated" + +class ClientAMDServerTestCase(ClientServerTestCase): + + def __init__(self, name="client/amd server", *args, **kargs): + ClientServerTestCase.__init__(self, name, *args, **kargs) + + def getServerType(self): + return "serveramd" + +class Result: + + def __init__(self, testsuite, writeToStdout): + self.testsuite = testsuite + self._skipped = [] + self._failed = {} + self._succeeded = [] + self._stdout = StringIO() + self._writeToStdout = writeToStdout + self._testcases = {} + + def started(self, testcase): + self._start = self._stdout.tell() + + def failed(self, testcase, exception): + self.writeln("test in {0} failed:\n{1}".format(self.testsuite, exception)) + self._testcases[testcase] = (self._start, self._stdout.tell()) + self._failed[testcase] = exception + + def succeeded(self, testcase): + self._testcases[testcase] = (self._start, self._stdout.tell()) + self._succeeded.append(testcase) + + def isSuccess(self): + return len(self._failed) == 0 + + def getFailed(self): + return self._failed + + def getOutput(self, testcase=None): + if testcase: + if testcase in self._testcases: + (start, end) = self._testcases[testcase] + self._stdout.seek(start) + try: + return self._stdout.read(end - start) + finally: + self._stdout.seek(os.SEEK_END) + + return self._stdout.getvalue() + + def write(self, msg, stdout=True): + if self._writeToStdout and stdout: + sys.stdout.write(msg) + sys.stdout.flush() + self._stdout.write(msg) + + def writeln(self, msg, stdout=True): + if self._writeToStdout and stdout: + print(msg) + self._stdout.write(msg + "\n") + +class TestSuite: + + def __init__(self, path, testcases=None, options={}, libDirs=[], runOnMainThread=False, chdir=False, multihost=True): + self.path = os.path.dirname(path) if os.path.basename(path) == "test.py" else path + self.mapping = Mapping.getByPath(self.path) + self.id = self.mapping.addTestSuite(self) + self.options = options + self.libDirs = libDirs + self.runOnMainThread = runOnMainThread + self.chdir = chdir + self.multihost = multihost + if self.chdir: + # Only tests running on main thread can change the current working directory + self.runOnMainThread = True + self.files = [] + if testcases is None: + files = [f for f in os.listdir(self.path) if os.path.isfile(os.path.join(self.path, f))] + testcases = self.mapping.computeTestCases(self.id, files) + self.testcases = OrderedDict() + for testcase in testcases if testcases else []: + testcase.init(self.mapping, self) + if testcase.name in self.testcases: + raise RuntimeError("duplicate testcase {0} in testsuite {1}".format(testcase, self)) + self.testcases[testcase.name] = testcase + + def __str__(self): + return self.id + + def getId(self): + return self.id + + def getOptions(self): + return self.options + + def getPath(self): + return self.path + + def getMapping(self): + return self.mapping + + def getLibDirs(self): + return self.libDirs + + def isMainThreadOnly(self): + for m in [CppMapping, JavaMapping, CSharpMapping]: + if isinstance(self.mapping, m): + return self.runOnMainThread + else: + return True + + def addTestCase(self, testcase): + if testcase.name in self.testcases: + raise RuntimeError("duplicate testcase {0} in testsuite {1}".format(testcase, self)) + testcase.init(self.mapping, self) + self.testcases[testcase.name] = testcase + + def findTestCase(self, testcase): + return self.testcases.get(testcase if isinstance(testcase, str) else testcase.name) + + def getTestCases(self): + return self.testcases.values() + + def setup(self, current): + pass + + def run(self, current): + try: + cwd=None + if self.chdir: + cwd = os.getcwd() + os.chdir(self.path) + current.driver.runTestSuite(current) + finally: + if cwd: os.chdir(cwd) + for f in self.files: + if os.path.exists(f): os.remove(f) + + def teardown(self, current, success): + pass + + def createFile(self, path, lines, encoding=None): + path = os.path.join(self.path, path.decode("utf-8") if isPython2 else path) + with open(path, "w", encoding=encoding) if not isPython2 and encoding else open(path, "wb") as file: + for l in lines: + file.write("%s\n" % l) + self.files.append(path) + + def isMultiHost(self): + return self.multihost + + def isCross(self): + # Only run the tests that support cross testing --all-cross or --cross + return self.id in self.mapping.getCrossTestSuites() + + def isAllCross(self): + # Only run the Ice/operations test suite with --all-cross + return self.id == "Ice/operations" + +class Driver: + + class Current: + + def __init__(self, driver, testsuite, result): + self.driver = driver + self.testsuite = testsuite + self.config = driver.configs[testsuite.getMapping()] + self.result = result + self.host = None + self.testcase = None + self.testcases = [] + + def getTestEndpoint(self, *args, **kargs): + return self.driver.getTestEndpoint(*args, **kargs) + + def getBuildDir(self, name): + return self.testcase.getMapping().getBuildDir(name, self) + + def getPluginEntryPoint(self, plugin): + return self.testcase.getMapping().getPluginEntryPoint(plugin) + + def write(self, *args, **kargs): + self.result.write(*args, **kargs) + + def writeln(self, *args, **kargs): + self.result.writeln(*args, **kargs) + + def push(self, testcase): + if not testcase.mapping: + assert(not testcase.parent and not testcase.testsuite) + testcase.mapping = self.testcase.getMapping() + testcase.testsuite = self.testcase.getTestSuite() + testcase.parent = self.testcase + self.testcases.append(self.testcase) + self.testcase = testcase + + def pop(self): + assert(self.testcase) + testcase = self.testcase + self.testcase = self.testcases.pop() + if testcase.parent and self.testcase != testcase: + testcase.mapping = None + testcase.testsuite = None + testcase.parent = None + + drivers = {} + driver = "local" + + @classmethod + def add(self, name, driver, default=False): + if default: + Driver.driver = name + self.driver = name + self.drivers[name] = driver + + @classmethod + def getAll(self): + return self.drivers.values() + + @classmethod + def create(self, options): + parseOptions(self, options) + driver = self.drivers.get(self.driver) + if not driver: + raise RuntimeError("unknown driver `{0}'".format(self.driver)) + return driver(options) + + @classmethod + def getOptions(self): + return ("dlrR", ["debug", "driver=", "filter=", "rfilter=", "host=", "host-ipv6=", "host-bt="]) + + @classmethod + def usage(self): + pass + + @classmethod + def commonUsage(self): + print("") + print("Driver options:") + print("-d | --debug Verbose information.") + print("--driver=<driver> Use the given driver (local, client, server or remote).") + print("--filter=<regex> Run all the tests that match the given regex.") + print("--rfilter=<regex> Run all the tests that do not match the given regex.") + print("--host=<addr> The IPv4 address to use for Ice.Default.Host.") + print("--host-ipv6=<addr> The IPv6 address to use for Ice.Default.Host.") + print("--host-bt=<addr> The Bluetooth address to use for Ice.Default.Host.") + + def __init__(self, options): + self.debug = False + self.filters = [] + self.rfilters = [] + self.host = "" + self.hostIPv6 = "" + self.hostBT = "" + self.failures = [] + parseOptions(self, options, { "d": "debug", + "r" : "filters", + "R" : "rfilters", + "filter" : "filters", + "rfilter" : "rfilters", + "host-ipv6" : "hostIPv6", + "host-bt" : "hostBT" }) + + self.filters = [re.compile(re.escape(a)) for a in self.filters] + self.rfilters = [re.compile(re.escape(a)) for a in self.rfilters] + + def setConfigs(self, configs): + self.configs = configs + + def useBinDist(self): + return os.environ.get("USE_BIN_DIST", "no") == "yes" + + def getIceDir(self, mapping=None): + if self.useBinDist(): + iceHome = os.environ.get("ICE_HOME", "") + return iceHome if iceHome else platform.getIceDir() + elif mapping: + return mapping.getPath() + else: + return toplevel + + def getSliceDir(self): + return platform.getSliceDir(self.getIceDir()) + + def isWorkerThread(self): + return False + + def getTestEndpoint(self, portnum, protocol="default"): + return "{0} -p {1}".format(protocol, self.getTestPort(portnum)) + + def getTestPort(self, portnum): + return 12010 + portnum + + def getArgs(self, process, current): + ### Return driver specific arguments + return [] + + def getProps(self, process, current): + props = {} + if isinstance(process, IceProcess): + if not self.host: + props["Ice.Default.Host"] = "0:0:0:0:0:0:0:1" if current.config.ipv6 else "127.0.0.1" + else: + props["Ice.Default.Host"] = self.host + return props + + def getMappings(self): + ### Return additional mappings to load required by the driver + return [] + + def destroy(self): + pass + + +class CppMapping(Mapping): + + class Config(Mapping.Config): + + def __init__(self, options): + Mapping.Config.__init__(self, options) + + # Derive from the build config the cpp11 option. This is used by canRun to allow filtering + # tests on the cpp11 value in the testcase options specification + self.cpp11 = self.buildConfig.lower().find("cpp11") >= 0 + + def canRun(self, current): + if not Mapping.Config.canRun(self, current): + return False + + # No C++11 tests for IceStorm, IceGrid, etc + parent = re.match(r'^([\w]*).*', current.testcase.getTestSuite().getId()).group(1) + if self.cpp11 and not parent in ["IceUtil", "Slice", "Ice", "IceSSL", "IceDiscovery", "IceBox"]: + return False + + return True + + def createConfig(self, options): + return CppMapping.Config(options) + + def getDefaultExe(self, processType, config): + return platform.getDefaultExe(processType, config) + + def getProps(self, process, current): + props = Mapping.getProps(self, process, current) + if isinstance(process, IceProcess): + props["Ice.NullHandleAbort"] = True + return props + + def getSSLProps(self, process, protocol="ssl"): + props = Mapping.getSSLProps(self, process, protocol) + props.update({ + "IceSSL.Password": "password", + "IceSSL.DefaultDir": os.path.join(toplevel, "certs"), + "IceSSL.CAs": "cacert.pem", + "IceSSL.VerifyPeer": "0" if protocol == "wss" else "2", + "IceSSL.CertFile": "server.p12" if isinstance(process, Server) else "client.p12", + }) + if isinstance(platform, Darwin): + props.update({ + "IceSSL.KeychainPassword" : "password", + "IceSSL.Keychain": "server.keychain" if isinstance(process, Server) else "client.keychain" + }) + return props + + def getPluginEntryPoint(self, plugin): + return { + "IceSSL" : "IceSSL:createIceSSL", + "IceBT" : "IceBT:createIceBT", + "IceDiscovery" : "IceDiscovery:createIceDiscovery" + }[plugin] + + def getEnv(self, process, current): + + # + # On Windows, add the testcommon directories to the PATH + # + libPaths = [] + if isinstance(platform, Windows): + libPaths.append(self.getLibDir(current)) + testcommon = os.path.join(self.path, "test", "Common") + libPaths.append(os.path.join(testcommon, self.getBuildDir("testcommon", current))) + + # + # Add the test suite library directories to the platform library path environment variable. + # + if current.testcase: + for d in set([current.getBuildDir(d) for d in current.testcase.getTestSuite().getLibDirs()]): + libPaths.append(current.getBuildDir(d)) + + env = {} + if len(libPaths) > 0: + env[platform.getLdPathEnvName()] = os.pathsep.join(libPaths) + return env + + def getDefaultSource(self, processType): + return { + "client" : "Client.cpp", + "server" : "Server.cpp", + "serveramd" : "ServerAMD.cpp", + "collocated" : "Collocated.cpp", + }[processType] + +class JavaMapping(Mapping): + + def getCommandLine(self, current, process, exe): + if process.isFromBinDir(): + return "java {0}".format(exe) + + assert(current.testcase.getPath().startswith(self.getTestsPath())) + package = "test." + current.testcase.getPath()[len(self.getTestsPath()) + 1:].replace(os.sep, ".") + return "java {0}.{1}".format(package, exe) + + def getSSLProps(self, process, protocol="ssl"): + props = Mapping.getSSLProps(self, process, protocol) + props.update({ + "IceSSL.Password": "password", + "IceSSL.DefaultDir": os.path.join(toplevel, "certs"), + "IceSSL.VerifyPeer": "0" if protocol == "wss" else "2", + "IceSSL.Keystore": "server.jks" if isinstance(process, Server) else "client.jks", + }) + return props + + def getPluginEntryPoint(self, plugin): + return { + "IceSSL" : "com.zeroc.IceSSL.PluginFactory", + "IceBT" : "com.zeroc.IceBT.PluginFactory", + "IceDiscovery" : "com.zeroc.IceDiscovery.PluginFactory" + }[plugin] + + def getEnv(self, process, current): + return { "CLASSPATH" : os.path.join(self.path, "lib", "test.jar") } + + def getTestsPath(self): + return os.path.join(self.path, "test/src/main/java/test") + + def getDefaultSource(self, processType): + return self.getDefaultExe(processType) + ".java" + + def getDefaultExe(self, processType, config=None): + return { + "client" : "Client", + "server" : "Server", + "serveramd" : "AMDServer", + "collocated" : "Collocated", + "icebox": "com.zeroc.IceBox.Server", + "iceboxadmin" : "com.zeroc.IceBox.Admin", + }[processType] + +class JavaCompatMapping(JavaMapping): + + def getPluginEntryPoint(self, plugin): + return { + "IceSSL" : "IceSSL.PluginFactory", + "IceBT" : "IceBT.PluginFactory", + "IceDiscovery" : "IceDiscovery.PluginFactory" + }[plugin] + + def getDefaultExe(self, processType, config=None): + return { + "client" : "Client", + "server" : "Server", + "serveramd" : "AMDServer", + "collocated" : "Collocated", + "icebox": "IceBox.Server", + "iceboxadmin" : "IceBox.Admin", + }[processType] + +class CSharpMapping(Mapping): + + def getBuildDir(self, name, current): + # Executables are not produced in build sub-directory with the C# mapping. + return "" + + def getSSLProps(self, process, protocol="ssl"): + props = Mapping.getSSLProps(self, process, protocol) + props.update({ + "IceSSL.Password": "password", + "IceSSL.DefaultDir": os.path.join(toplevel, "certs"), + "IceSSL.CAs": "cacert.pem", + "IceSSL.VerifyPeer": "0" if protocol == "wss" else "2", + "IceSSL.CertFile": "server.p12" if isinstance(process, Server) else "client.p12", + }) + return props + + def getPluginEntryPoint(self, plugin): + return { + "IceSSL" : "{icedir}/Assemblies/IceSSL.dll:IceSSL.PluginFactory", + "IceDiscovery" : "{icedir}/Assemblies/IceDiscovery.dll:IceDiscovery.PluginFactory" + }[plugin] + + def getEnv(self, process, current): + if current.driver.useBinDist(): + bzip2 = Mapping.getByName("cpp").getLibDir(current) + else: + bzip2 = os.path.join(toplevel, "cpp", "msbuild", "packages", + "bzip2.{0}.1.0.6.4".format(platform.getCompiler()), + "build", "native", "bin", "x64", "Release") + + return { "DEVPATH" : os.path.join(current.driver.getIceDir(self), "Assemblies"), "PATH" : bzip2 }; + + def getDefaultSource(self, processType): + return { + "client" : "Client.cs", + "server" : "Server.cs", + "serveramd" : "ServerAMD.cs", + "collocated" : "Collocated.cs", + }[processType] + + def getDefaultExe(self, processType, config): + return "iceboxnet" if processType == "icebox" else processType + +class CppBasedMapping(Mapping): + + def getSSLProps(self, process, protocol="ssl"): + return Mapping.getByName("cpp").getSSLProps(process, protocol) + + def getPluginEntryPoint(self, plugin): + return Mapping.getByName("cpp").getPluginEntryPoint(plugin) + + def getEnv(self, process, current): + env = Mapping.getEnv(self, process, current) + if current.driver.getIceDir() != platform.getIceDir(): + # If not installed in the default platform installation directory, add + # the Ice C++ library directory to the library path + env[platform.getLdPathEnvName()] = Mapping.getByName("cpp").getLibDir(current) + return env + +class ObjCMapping(CppBasedMapping): + + def getDefaultSource(self, processType): + return { + "client" : "Client.m", + "server" : "Server.m", + "collocated" : "Collocated.m", + }[processType] + +class PythonMapping(CppBasedMapping): + + def getCommandLine(self, current, process, exe): + return sys.executable + " " + exe + + def getEnv(self, process, current): + env = CppBasedMapping.getEnv(self, process, current) + if current.driver.getIceDir() != platform.getIceDir(): + # If not installed in the default platform installation directory, add + # the Ice python directory to PYTHONPATH + env["PYTHONPATH"] = os.path.join(current.driver.getIceDir(self), "python") + return env + + def getDefaultExe(self, processType, config): + return self.getDefaultSource(processType) + + def getDefaultSource(self, processType): + return { + "client" : "Client.py", + "server" : "Server.py", + "serveramd" : "ServerAMD.py", + "collocated" : "Collocated.py", + }[processType] + +class CppBasedClientMapping(CppBasedMapping): + + def loadTestSuites(self, tests, filters, rfilters): + Mapping.loadTestSuites(self, tests, filters, rfilters) + self.getServerMapping().loadTestSuites(self.testsuites.keys()) + + def getServerMapping(self): + return Mapping.getByName("cpp") # By default, run clients against C++ mapping executables + + def getDefaultExe(self, processType, config): + return self.getDefaultSource(processType) + +class RubyMapping(CppBasedClientMapping): + + def getCommandLine(self, current, process, exe): + return "ruby " + exe + + def getEnv(self, process, current): + env = CppBasedMapping.getEnv(self, process, current) + if current.driver.getIceDir() != platform.getIceDir(): + # If not installed in the default platform installation directory, add + # the Ice ruby directory to RUBYLIB + env["RUBYLIB"] = os.path.join(self.path, "ruby") + return env + + def getDefaultSource(self, processType): + return { "client" : "Client.rb" }[processType] + +class PhpMapping(CppBasedClientMapping): + + def getCommandLine(self, current, process, exe): + args = [] + if current.driver.getIceDir() == platform.getIceDir(): + # + # If installed in the platform system directory and on Linux, we rely + # on ice.ini to find the extension. On OS X, we still need to setup + # the properties. + # + if(isinstance(platform, Darwin)): + args += ["-d", "extension_dir=/usr/local/lib/php/extensions"] + args += ["-d", "include_path=/usr/local/share/php"] + args += ["-d", "extension=IcePHP.so"] + else: + args += ["-d", "extension_dir='{0}'".format(self.getLibDir(current))] + args += ["-d", "extension='{0}'".format("php_ice.dll" if isinstance(platform, Windows) else "IcePHP.so")] + args += ["-d", "include_path='{0}'".format(self.getLibDir(current))] + if hasattr(process, "getPhpArgs"): + args += process.getPhpArgs(current) + return "php {0} -f {1} -- ".format(" ".join(args), exe) + + def getDefaultSource(self, processType): + return { "client" : "Client.php" }[processType] + +class JavaScriptMapping(Mapping): + + class Config(Mapping.Config): + + @classmethod + def getOptions(self): + return ("", ["es5"]) + + @classmethod + def usage(self): + print("") + print("JavaScript mapping options:") + print("--es5 Use JavaScript ES5 (Babel compiled code).") + + def __init__(self, options=[]): + Mapping.Config.__init__(self, options) + self.es5 = False + parseOptions(self, options) + + def createConfig(self, options): + return JavaScriptMapping.Config(options) + + def loadTestSuites(self, tests, filters, rfilters): + Mapping.loadTestSuites(self, tests, filters, rfilters) + self.getServerMapping().loadTestSuites(self.testsuites.keys() + ["Ice/echo"]) + + def getServerMapping(self): + return Mapping.getByName("cpp") # By default, run clients against C++ mapping executables + + def getCommandLine(self, current, process, exe): + if current.config.es5: + return "node {0}/test/Common/run.js --es5 {1}".format(self.path, exe) + else: + return "node {0}/test/Common/run.js {1}".format(self.path, exe) + + def getDefaultSource(self, processType): + return { "client" : "Client.js", "clientBidir" : "ClientBidir.js" }[processType] + + def getDefaultExe(self, processType, config=None): + return self.getDefaultSource(processType).replace(".js", "") + + def getEnv(self, process, current): + env = Mapping.getEnv(self, process, current) + env["NODE_PATH"] = self.getTestCwd(current) + return env + + def getTestCwd(self, current): + if current.config.es5: + # Change to the ES5 test directory if testing ES5 + return os.path.join(self.path, "test", "es5", current.testcase.getTestSuite().getId()) + else: + return os.path.join(self.path, "test", current.testcase.getTestSuite().getId()) + + def computeTestCases(self, testId, files): + if testId.find("es5") > -1: + return # Ignore es5 directories + return Mapping.computeTestCases(self, testId, files) + + def getOptions(self): + # JavaScript with NodeJS only supports tcp and no other options + return { "protocol" : ["tcp"], "compress" : [False], "ipv6" : [False], "serialize" : [False], "mx" : [False] } + +from Glacier2Util import * +from IceBoxUtil import * +from IceGridUtil import * +from IceStormUtil import * +from IcePatch2Util import * +from LocalDriver import * + +# +# Supported mappings +# +Mapping.add("cpp", CppMapping()) +Mapping.add("java", JavaMapping()) +Mapping.add("java-compat", JavaCompatMapping()) +Mapping.add("python", PythonMapping()) +Mapping.add("ruby", RubyMapping()) +Mapping.add("php", PhpMapping()) +Mapping.add("js", JavaScriptMapping()) +if isinstance(platform, Windows): + Mapping.add("csharp", CSharpMapping()) +if isinstance(platform, Darwin): + Mapping.add("objective-c", ObjCMapping()) + +def runTestsWithPath(path): + runTests([Mapping.getByPath(path)]) + +def runTests(mappings=None, drivers=None): + if not mappings: + mappings = Mapping.getAll() + if not drivers: + drivers = Driver.getAll() + + def usage(): + print("Usage: " + sys.argv[0] + " [options] [tests]") + print("") + print("Options:") + print("-h | --help Show this message") + + Driver.commonUsage() + for driver in drivers: + driver.usage() + + Mapping.Config.commonUsage() + for mapping in mappings: + mapping.Config.usage() + + print("") + + driver = None + try: + options = [Driver.getOptions(), Mapping.Config.getOptions()] + options += [driver.getOptions() for driver in drivers] + options += [mapping.Config.getOptions() for mapping in mappings] + shortOptions = "h" + longOptions = ["help"] + for so, lo in options: + shortOptions += so + longOptions += lo + opts, args = getopt.gnu_getopt(sys.argv[1:], shortOptions, longOptions) + + for (o, a) in opts: + if o in ["-h", "--help"]: + usage() + sys.exit(0) + + # + # Create the driver + # + driver = Driver.create(opts) + + # + # Create the configurations for each mapping + # + configs = {} + for mapping in mappings: + configs[mapping] = mapping.createConfig(opts) + + if len(opts) > 0: + print(sys.argv[0] + ": unknown options {0}".format(opts)) + usage() + sys.exit(1) + + # + # Provide the configurations to the driver and load the test suites for each mapping. + # + driver.setConfigs(configs) + for mapping in mappings + driver.getMappings(): + mapping.loadTestSuites(args, driver.filters, driver.rfilters) + + # + # Finally, run the test suites with the driver. + # + try: + driver.run(mappings) + except KeyboardInterrupt: + pass + finally: + driver.destroy() + + except Exception as e: + print(sys.argv[0] + ": unexpected exception raised:\n" + traceback.format_exc()) + sys.exit(1) diff --git a/scripts/__init__.py b/scripts/__init__.py index d6227364c08..90d182d1c05 100644 --- a/scripts/__init__.py +++ b/scripts/__init__.py @@ -6,5 +6,3 @@ # ICE_LICENSE file included in this distribution. # # ********************************************************************** - -__all__ = [ "Expect", "IceGridAdmin", "IceStormUtil", "TestUtil"] diff --git a/scripts/tests/Glacier2/__init__.py b/scripts/tests/Glacier2/__init__.py new file mode 100644 index 00000000000..90d182d1c05 --- /dev/null +++ b/scripts/tests/Glacier2/__init__.py @@ -0,0 +1,8 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** diff --git a/scripts/tests/Glacier2/router.py b/scripts/tests/Glacier2/router.py new file mode 100644 index 00000000000..f3f1a5b4aa0 --- /dev/null +++ b/scripts/tests/Glacier2/router.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +passwords = { + "userid": "abc123", + "userid-0": "abc123", + "userid-1": "abc123", + "userid-2": "abc123", + "userid-3": "abc123", + "userid-4": "abc123" +} + +routerProps = { + "Ice.Warn.Dispatch" : "0", + "Ice.Warn.Connections" : "0", + "Glacier2.Filter.Category.Accept" : "c1 c2", + "Glacier2.Filter.Category.AcceptUser" : "2", + "Glacier2.SessionTimeout" : "30", +} + +def buffered(enabled): + return { "Glacier2.Client.Buffered": enabled, "Glacier2.Server.Buffered": enabled } + +Glacier2TestSuite(__name__, routerProps, [ + ClientServerTestCase(name="client/server with router in unbuffered mode", + servers=[Glacier2Router(passwords=passwords, props=buffered(False)), Server()], + client=Client(args=["--shutdown"])), + ClientServerTestCase(name="client/server with router in buffered mode", + servers=[Glacier2Router(passwords=passwords, props=buffered(True)), Server()], + clients=[Client(), Client(args=["--shutdown"])])]) + diff --git a/scripts/tests/Glacier2/sessionHelper.py b/scripts/tests/Glacier2/sessionHelper.py new file mode 100644 index 00000000000..f9d802901c8 --- /dev/null +++ b/scripts/tests/Glacier2/sessionHelper.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +Glacier2TestSuite(__name__, routerProps = { "Glacier2.SessionTimeout" : 30 }) diff --git a/scripts/tests/Ice/__init__.py b/scripts/tests/Ice/__init__.py new file mode 100644 index 00000000000..90d182d1c05 --- /dev/null +++ b/scripts/tests/Ice/__init__.py @@ -0,0 +1,8 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** diff --git a/scripts/tests/Ice/adapterDeactivation.py b/scripts/tests/Ice/adapterDeactivation.py new file mode 100644 index 00000000000..deb29ba6b5f --- /dev/null +++ b/scripts/tests/Ice/adapterDeactivation.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, multihost=False)
\ No newline at end of file diff --git a/scripts/tests/Ice/admin.py b/scripts/tests/Ice/admin.py new file mode 100644 index 00000000000..a87c0754c69 --- /dev/null +++ b/scripts/tests/Ice/admin.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, options = { "ipv6" : [False] }, multihost=False)
\ No newline at end of file diff --git a/scripts/tests/Ice/ami.py b/scripts/tests/Ice/ami.py new file mode 100644 index 00000000000..6e5abe02f7f --- /dev/null +++ b/scripts/tests/Ice/ami.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, options = { "compress" : [False] })
\ No newline at end of file diff --git a/scripts/tests/Ice/background.py b/scripts/tests/Ice/background.py new file mode 100644 index 00000000000..4db72200a79 --- /dev/null +++ b/scripts/tests/Ice/background.py @@ -0,0 +1,10 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, libDirs=["testtransport"], options={ "mx": [False] }) diff --git a/scripts/tests/Ice/enums.py b/scripts/tests/Ice/enums.py new file mode 100644 index 00000000000..1780057f1a5 --- /dev/null +++ b/scripts/tests/Ice/enums.py @@ -0,0 +1,13 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, [ + ClientServerTestCase("client/server with default encoding"), + ClientServerTestCase("client/server with 1.0 encoding", props={ "Ice.Default.EncodingVersion" : "1.0" }), +])
\ No newline at end of file diff --git a/scripts/tests/Ice/exceptions.py b/scripts/tests/Ice/exceptions.py new file mode 100644 index 00000000000..0e2ac209032 --- /dev/null +++ b/scripts/tests/Ice/exceptions.py @@ -0,0 +1,24 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +testcases = [ + ClientServerTestCase("client/server with compact format"), + ClientServerTestCase("client/server with sliced format", props={ "Ice.Default.SlicedFormat" : True }), + ClientServerTestCase("client/server with 1.0 encoding", props={ "Ice.Default.EncodingVersion" : "1.0" }), +] + +# If the mapping has AMD servers, also run with the AMD servers +if Mapping.getByPath(__name__).hasSource("Ice/exceptions", "serveramd"): + testcases += [ + ClientAMDServerTestCase("client/amd server with compact format"), + ClientAMDServerTestCase("client/amd server with sliced format", props={ "Ice.Default.SlicedFormat" : True }), + ClientAMDServerTestCase("client/amd server with 1.0 encoding", props={ "Ice.Default.EncodingVersion" : "1.0" }), + ] + +TestSuite(__name__, testcases)
\ No newline at end of file diff --git a/scripts/tests/Ice/faultTolerance.py b/scripts/tests/Ice/faultTolerance.py new file mode 100755 index 00000000000..6cc55446826 --- /dev/null +++ b/scripts/tests/Ice/faultTolerance.py @@ -0,0 +1,20 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +from Util import * + +# +# Start 12 servers +# +servers=range(1, 13) + +TestSuite(__name__, [ + ClientServerTestCase(client=Client(args=[i for i in servers]), + servers=[Server(args=[i], waitForShutdown=False) for i in servers]) +]) diff --git a/scripts/tests/Ice/hold.py b/scripts/tests/Ice/hold.py new file mode 100644 index 00000000000..a3889c461b7 --- /dev/null +++ b/scripts/tests/Ice/hold.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, [ClientServerTestCase(server=Server(readyCount=2))]) diff --git a/scripts/tests/Ice/info.py b/scripts/tests/Ice/info.py new file mode 100644 index 00000000000..e42ee312f56 --- /dev/null +++ b/scripts/tests/Ice/info.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, options = { "ipv6" : [False], "compress" : [False] }, multihost=False)
\ No newline at end of file diff --git a/scripts/tests/Ice/interceptor.py b/scripts/tests/Ice/interceptor.py new file mode 100644 index 00000000000..1db4578f24b --- /dev/null +++ b/scripts/tests/Ice/interceptor.py @@ -0,0 +1,10 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, [ClientTestCase(client=Client(props={"Ice.Warn.Dispatch" : 0}))], libDirs=["interceptortest"]) diff --git a/scripts/tests/Ice/interrupt.py b/scripts/tests/Ice/interrupt.py new file mode 100644 index 00000000000..6e5abe02f7f --- /dev/null +++ b/scripts/tests/Ice/interrupt.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, options = { "compress" : [False] })
\ No newline at end of file diff --git a/scripts/tests/Ice/metrics.py b/scripts/tests/Ice/metrics.py new file mode 100644 index 00000000000..e81bc4b22af --- /dev/null +++ b/scripts/tests/Ice/metrics.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, options = { "ipv6" : [False], "compress": [False], "protocol" : ["tcp", "ssl"] }, multihost=False) diff --git a/scripts/tests/Ice/networkProxy.py b/scripts/tests/Ice/networkProxy.py new file mode 100644 index 00000000000..948b24b2e7c --- /dev/null +++ b/scripts/tests/Ice/networkProxy.py @@ -0,0 +1,38 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import NetworkProxy + +class NetworkProxyTestCase(ClientServerTestCase): + + def __init__(self, proxyName, proxyType, proxyPortNum): + ClientServerTestCase.__init__(self, proxyName + " client/server", client = Client(props = lambda p, c: { + "Ice.{0}ProxyHost".format(proxyName): "localhost", + "Ice.{0}ProxyPort".format(proxyName): "{0}".format(c.driver.getTestPort(proxyPortNum)) + })) + self.proxyName = proxyName + self.proxyType = proxyType + self.proxyPortNum = proxyPortNum + self.proxy = None + + def setupClientSide(self, current): + current.write("starting {0} proxy... ".format(self.proxyName)) + self.proxy = self.proxyType(current.driver.getTestPort(self.proxyPortNum)) + current.writeln("ok") + + def teardownClientSide(self, current, success): + current.write("terminating {0} proxy... ".format(self.proxyName)) + self.proxy.terminate() + self.proxy = None + current.writeln("ok") + +TestSuite(__name__, [ + NetworkProxyTestCase("SOCKS", NetworkProxy.SocksProxy, 30), + NetworkProxyTestCase("HTTP", NetworkProxy.HttpProxy, 31), +], options = { "ipv6" : [False] }) diff --git a/scripts/tests/Ice/objects.py b/scripts/tests/Ice/objects.py new file mode 100644 index 00000000000..fef2b3fb6cb --- /dev/null +++ b/scripts/tests/Ice/objects.py @@ -0,0 +1,14 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, [ + ClientServerTestCase("client/server with compact format"), + ClientServerTestCase("client/server with sliced format", props={ "Ice.Default.SlicedFormat" : True }), + ClientServerTestCase("client/server with 1.0 encoding", props={ "Ice.Default.EncodingVersion" : "1.0" }), +])
\ No newline at end of file diff --git a/scripts/tests/Ice/optional.py b/scripts/tests/Ice/optional.py new file mode 100644 index 00000000000..b706d197749 --- /dev/null +++ b/scripts/tests/Ice/optional.py @@ -0,0 +1,23 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + + +testcases = [ + ClientServerTestCase("client/server with compact format"), + ClientServerTestCase("client/server with sliced format", props={ "Ice.Default.SlicedFormat" : True }), +] + +# If the mapping has AMD servers, also run with the AMD servers +if Mapping.getByPath(__name__).hasSource("Ice/exceptions", "serveramd"): + testcases += [ + ClientAMDServerTestCase("client/amd server with compact format"), + ClientAMDServerTestCase("client/amd server with sliced format", props={ "Ice.Default.SlicedFormat" : True }), + ] + +TestSuite(__name__, testcases)
\ No newline at end of file diff --git a/scripts/tests/Ice/properties.py b/scripts/tests/Ice/properties.py new file mode 100644 index 00000000000..92a9832aa61 --- /dev/null +++ b/scripts/tests/Ice/properties.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +class PropertiesTestSuite(TestSuite): + + def setup(self, current): + name = "\xe4\xb8\xad\xe5\x9b\xbd_client.config" if isPython2 else "\u4e2d\u56fd_client.config" + self.createFile("./config/" + name, + ["# Automatically generated by Ice test driver.", + "Ice.Trace.Protocol=1", + "Ice.Trace.Network=1", + "Ice.ProgramName=PropertiesClient", + "Config.Path=./config/" + name], + "utf-8") + +PropertiesTestSuite(__name__) diff --git a/scripts/tests/Ice/slicing/__init__.py b/scripts/tests/Ice/slicing/__init__.py new file mode 100644 index 00000000000..90d182d1c05 --- /dev/null +++ b/scripts/tests/Ice/slicing/__init__.py @@ -0,0 +1,8 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** diff --git a/scripts/tests/Ice/slicing/exceptions.py b/scripts/tests/Ice/slicing/exceptions.py new file mode 100644 index 00000000000..beb5f64484a --- /dev/null +++ b/scripts/tests/Ice/slicing/exceptions.py @@ -0,0 +1,22 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +testcases = [ + ClientServerTestCase(), + ClientServerTestCase("client/server with 1.0 encoding", props={ "Ice.Default.EncodingVersion" : "1.0" }), +] + +# If the mapping has AMD servers, also run with the AMD servers +if Mapping.getByPath(__name__).hasSource("Ice/exceptions", "serveramd"): + testcases += [ + ClientAMDServerTestCase(), + ClientAMDServerTestCase("client/amd server with 1.0 encoding", props={ "Ice.Default.EncodingVersion" : "1.0" }), + ] + +TestSuite(__name__, testcases)
\ No newline at end of file diff --git a/scripts/tests/Ice/slicing/objects.py b/scripts/tests/Ice/slicing/objects.py new file mode 100644 index 00000000000..c1d57969e85 --- /dev/null +++ b/scripts/tests/Ice/slicing/objects.py @@ -0,0 +1,13 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, [ + ClientServerTestCase(), + ClientServerTestCase("client/server with 1.0 encoding", props={ "Ice.Default.EncodingVersion" : "1.0" }), +])
\ No newline at end of file diff --git a/scripts/tests/Ice/stream.py b/scripts/tests/Ice/stream.py new file mode 100644 index 00000000000..30fecbf5b9e --- /dev/null +++ b/scripts/tests/Ice/stream.py @@ -0,0 +1,14 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + + +TestSuite(__name__, [ + ClientTestCase("client with default encoding"), + ClientTestCase("client with 1.0 encoding", props={ "Ice.Default.EncodingVersion" : "1.0" }) +])
\ No newline at end of file diff --git a/scripts/tests/Ice/timeout.py b/scripts/tests/Ice/timeout.py new file mode 100644 index 00000000000..6e5abe02f7f --- /dev/null +++ b/scripts/tests/Ice/timeout.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, options = { "compress" : [False] })
\ No newline at end of file diff --git a/scripts/tests/Ice/udp.py b/scripts/tests/Ice/udp.py new file mode 100644 index 00000000000..214d9aaf8f3 --- /dev/null +++ b/scripts/tests/Ice/udp.py @@ -0,0 +1,19 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +from Util import * + +# +# Start 5 servers +# +servers=range(0, 5) + +TestSuite(__name__, [ + ClientServerTestCase(client=Client(args=[5]), servers=[Server(args=[i], ready="McastTestAdapter") for i in servers]) +], multihost=False) diff --git a/scripts/tests/IceBox/__init__.py b/scripts/tests/IceBox/__init__.py new file mode 100644 index 00000000000..90d182d1c05 --- /dev/null +++ b/scripts/tests/IceBox/__init__.py @@ -0,0 +1,8 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** diff --git a/scripts/tests/IceBox/admin.py b/scripts/tests/IceBox/admin.py new file mode 100644 index 00000000000..cd36e7475f7 --- /dev/null +++ b/scripts/tests/IceBox/admin.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +class IceBoxAdminTestCase(ClientServerTestCase): + + def runClientSide(self, current): + + admin = IceBoxAdmin(args = ['--Ice.Config="{testdir}/config.admin"']) + current.write("testing service stop...") + admin.run(current, args=['stop', 'TestService']) + current.writeln("ok") + current.write("testing service start...") + admin.run(current, args=['start', 'TestService']) + current.writeln("ok") + current.write("testing shutdown...") + admin.run(current, args=['shutdown']) + current.writeln("ok") + +TestSuite(__name__, [ + ClientServerTestCase(server=IceBox(args=['--Ice.Config="{testdir}/config.icebox"'])), + IceBoxAdminTestCase("iceboxadmin", server=IceBox(args=['--Ice.Config="{testdir}/config.icebox"'])), +], libDirs=["testservice"], runOnMainThread=True, options={ "ipv6" : [False], "mx" : [False] }, multihost=False) diff --git a/scripts/tests/IceBox/configuration.py b/scripts/tests/IceBox/configuration.py new file mode 100644 index 00000000000..d8add442cba --- /dev/null +++ b/scripts/tests/IceBox/configuration.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +TestSuite(__name__, [ + ClientServerTestCase("client/server #1", server=IceBox(args=['--Ice.Config="{testdir}/config.icebox"'])), + ClientServerTestCase("client/server #2", server=IceBox(args=['--Ice.Config="{testdir}/config.icebox2"'])) +], libDirs=["testservice"], runOnMainThread=True, options={ "protocol" : ["tcp"], "ipv6" : [False], "mx" : [False] }, multihost=False) diff --git a/scripts/tests/IceDiscovery/__init__.py b/scripts/tests/IceDiscovery/__init__.py new file mode 100644 index 00000000000..90d182d1c05 --- /dev/null +++ b/scripts/tests/IceDiscovery/__init__.py @@ -0,0 +1,8 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** diff --git a/scripts/tests/IceDiscovery/simple.py b/scripts/tests/IceDiscovery/simple.py new file mode 100644 index 00000000000..36b4f86a39e --- /dev/null +++ b/scripts/tests/IceDiscovery/simple.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +# Client properties (plugin is loaded with Ice::registerPluginFactory) +props = lambda process, current: { + "IceDiscovery.Timeout": 50, + "IceDiscovery.RetryCount": 5, + "IceDiscovery.Interface": "127.0.0.1" if not current.config.ipv6 else "\"::1\"" if isinstance(platform, Darwin) else "", + "Ice.Plugin.IceDiscovery": current.getPluginEntryPoint("IceDiscovery") +} + +# Server properties (client properties + plugin configuration) +serverProps = lambda process, current: dict(itertools.chain({ + "Ice.Plugin.IceDiscovery": current.getPluginEntryPoint("IceDiscovery") +}.items(), props(process, current).items())) + +TestSuite(__name__, [ + ClientServerTestCase(client=Client(args=[3], props=props), + servers=[Server(args=[i], readyCount=4, props=serverProps) for i in range(0, 3)]) +], multihost=False) diff --git a/scripts/tests/IceGrid/__init__.py b/scripts/tests/IceGrid/__init__.py new file mode 100644 index 00000000000..90d182d1c05 --- /dev/null +++ b/scripts/tests/IceGrid/__init__.py @@ -0,0 +1,8 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** diff --git a/scripts/tests/IceGrid/simple.py b/scripts/tests/IceGrid/simple.py new file mode 100644 index 00000000000..379ebe790d9 --- /dev/null +++ b/scripts/tests/IceGrid/simple.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +serverProps = { + "TestAdapter.Endpoints" : "default", + "TestAdapter.AdapterId" : "TestAdapter" +} + +registryProps = { + "IceGrid.Registry.DynamicRegistration" : 1 +} + +TestSuite(__name__, [ + IceGridTestCase("without deployment", application=None, + icegridregistry=[IceGridRegistryMaster(props=registryProps), + IceGridRegistrySlave(1, props=registryProps), + IceGridRegistrySlave(2, props=registryProps)], + client=ClientServerTestCase(client=IceGridClient(), server=IceGridServer(props=serverProps))), + IceGridTestCase("with deployment", client=IceGridClient(args=["--with-deploy"])) +], multihost=False) diff --git a/scripts/tests/IceSSL/__init__.py b/scripts/tests/IceSSL/__init__.py new file mode 100644 index 00000000000..90d182d1c05 --- /dev/null +++ b/scripts/tests/IceSSL/__init__.py @@ -0,0 +1,8 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** diff --git a/scripts/tests/IceSSL/configuration.py b/scripts/tests/IceSSL/configuration.py new file mode 100644 index 00000000000..1d4f832b49f --- /dev/null +++ b/scripts/tests/IceSSL/configuration.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +class ConfigurationTestCase(ClientServerTestCase): + + def setupServerSide(self, current): + # Nothing to do if we're not running this test with the C++ mapping + if not isinstance(self.getMapping(), CppMapping): + return + + certsPath = os.path.abspath(os.path.join(self.getPath(), "..", "certs")) + if isinstance(platform, Darwin): + keychainPath = os.path.join(certsPath, "Find.keychain") + os.system("mkdir -p {0}".format(os.path.join(certsPath, "keychain"))) + os.system("security create-keychain -p password %s" % keychainPath) + for cert in ["s_rsa_ca1.p12", "c_rsa_ca1.p12"]: + os.system("security import %s -f pkcs12 -A -P password -k %s" % (os.path.join(certsPath, cert), keychainPath)) + elif platform.hasOpenSSL(): + # + # Create copies of the CA certificates named after the subject + # hash. This is used by the tests to find the CA certificates in + # the IceSSL.DefaultDir + # + for c in ["cacert1.pem", "cacert2.pem"]: + pem = os.path.join(certsPath, c) + os.system("cp {pem} {dir}/`openssl x509 -subject_hash -noout -in {pem}`.0".format(pem=pem, dir=certsPath)) + + def teardownServerSide(self, current, success): + # Nothing to do if we're not running this test with the C++ mapping + if not isinstance(self.getMapping(), CppMapping): + return + + certsPath = os.path.abspath(os.path.join(self.getPath(), "..", "certs")) + if isinstance(platform, Darwin): + os.system("rm -rf {0} {1}".format(os.path.join(certsPath, "keychain"), os.path.join(certsPath, "Find.keychain"))) + elif platform.hasOpenSSL(): + for c in ["cacert1.pem", "cacert2.pem"]: + pem = os.path.join(certsPath, c) + os.system("rm -f {dir}/`openssl x509 -subject_hash -noout -in {pem}`.0".format(pem=pem, dir=certsPath)) + +# Filter-out the deprecated property warnings +outfilters = [ lambda x: re.sub("-! .* warning: deprecated property: IceSSL.KeyFile\n", "", x) ] + +TestSuite(__name__, [ + ConfigurationTestCase(client=Client(outfilters=outfilters, args=['"{testdir}"']), + server=Server(outfilters=outfilters)) +], multihost=False) diff --git a/scripts/tests/__init__.py b/scripts/tests/__init__.py new file mode 100644 index 00000000000..90d182d1c05 --- /dev/null +++ b/scripts/tests/__init__.py @@ -0,0 +1,8 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** |