summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2016-11-25 13:13:22 +0100
committerBenoit Foucher <benoit@zeroc.com>2016-11-25 13:13:22 +0100
commitdcdc32af1fced49d80a8ccd93230e15d91ab45d8 (patch)
treeeb69e2555fbd54496fce8a33f4dd610e1473ff51 /scripts
parentC# IceSSL/configuration log expired certificate exceptions. (diff)
downloadice-dcdc32af1fced49d80a8ccd93230e15d91ab45d8.tar.bz2
ice-dcdc32af1fced49d80a8ccd93230e15d91ab45d8.tar.xz
ice-dcdc32af1fced49d80a8ccd93230e15d91ab45d8.zip
Refactored test scripts
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Controller.ice86
-rwxr-xr-xscripts/Controller.py263
-rwxr-xr-xscripts/Expect.py39
-rw-r--r--scripts/Glacier2Util.py76
-rw-r--r--scripts/IceBoxUtil.py27
-rw-r--r--scripts/IceGridAdmin.py329
-rw-r--r--scripts/IceGridUtil.py265
-rw-r--r--scripts/IcePatch2Util.py15
-rw-r--r--scripts/IceStormUtil.py441
-rw-r--r--scripts/LocalDriver.py521
-rw-r--r--scripts/NetworkProxy.py27
-rw-r--r--scripts/TestController.py97
-rwxr-xr-xscripts/TestUtil.py2669
-rw-r--r--scripts/Util.py2114
-rw-r--r--scripts/__init__.py2
-rw-r--r--scripts/tests/Glacier2/__init__.py8
-rw-r--r--scripts/tests/Glacier2/router.py38
-rw-r--r--scripts/tests/Glacier2/sessionHelper.py11
-rw-r--r--scripts/tests/Ice/__init__.py8
-rw-r--r--scripts/tests/Ice/adapterDeactivation.py11
-rw-r--r--scripts/tests/Ice/admin.py11
-rw-r--r--scripts/tests/Ice/ami.py11
-rw-r--r--scripts/tests/Ice/background.py10
-rw-r--r--scripts/tests/Ice/enums.py13
-rw-r--r--scripts/tests/Ice/exceptions.py24
-rwxr-xr-xscripts/tests/Ice/faultTolerance.py20
-rw-r--r--scripts/tests/Ice/hold.py11
-rw-r--r--scripts/tests/Ice/info.py11
-rw-r--r--scripts/tests/Ice/interceptor.py10
-rw-r--r--scripts/tests/Ice/interrupt.py11
-rw-r--r--scripts/tests/Ice/metrics.py11
-rw-r--r--scripts/tests/Ice/networkProxy.py38
-rw-r--r--scripts/tests/Ice/objects.py14
-rw-r--r--scripts/tests/Ice/optional.py23
-rw-r--r--scripts/tests/Ice/properties.py23
-rw-r--r--scripts/tests/Ice/slicing/__init__.py8
-rw-r--r--scripts/tests/Ice/slicing/exceptions.py22
-rw-r--r--scripts/tests/Ice/slicing/objects.py13
-rw-r--r--scripts/tests/Ice/stream.py14
-rw-r--r--scripts/tests/Ice/timeout.py11
-rw-r--r--scripts/tests/Ice/udp.py19
-rw-r--r--scripts/tests/IceBox/__init__.py8
-rw-r--r--scripts/tests/IceBox/admin.py29
-rw-r--r--scripts/tests/IceBox/configuration.py14
-rw-r--r--scripts/tests/IceDiscovery/__init__.py8
-rw-r--r--scripts/tests/IceDiscovery/simple.py27
-rw-r--r--scripts/tests/IceGrid/__init__.py8
-rw-r--r--scripts/tests/IceGrid/simple.py27
-rw-r--r--scripts/tests/IceSSL/__init__.py8
-rw-r--r--scripts/tests/IceSSL/configuration.py54
-rw-r--r--scripts/tests/__init__.py8
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.
+#
+# **********************************************************************