// ********************************************************************** // // Copyright (c) 2003-2017 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. // // ********************************************************************** using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using Test; #if SILVERLIGHT using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; #endif class LoggerI : Ice.Logger { public void start() { lock(this) { _started = true; dump(); } } public void print(string msg) { lock(this) { _messages.Add(msg); if(_started) { dump(); } } } public void trace(string category, string message) { lock(this) { _messages.Add("[" + category + "] " + message); if(_started) { dump(); } } } public void warning(string message) { lock(this) { _messages.Add("warning: " + message); if(_started) { dump(); } } } public void error(string message) { lock(this) { _messages.Add("error: " + message); if(_started) { dump(); } } } public string getPrefix() { return ""; } public Ice.Logger cloneWithPrefix(string prefix) { return this; } private void dump() { foreach(string line in _messages) { System.Console.WriteLine(line); } _messages.Clear(); } private bool _started; private List _messages = new List(); }; abstract class TestCase : Ice.ConnectionCallback { public TestCase(string name, RemoteCommunicatorPrx com) { _name = name; _com = com; _logger = new LoggerI(); _clientACMTimeout = -1; _clientACMClose = -1; _clientACMHeartbeat = -1; _serverACMTimeout = -1; _serverACMClose = -1; _serverACMHeartbeat = -1; _heartbeat = 0; _closed = false; } public void init() { _adapter = _com.createObjectAdapter(_serverACMTimeout, _serverACMClose, _serverACMHeartbeat); Ice.InitializationData initData = new Ice.InitializationData(); initData.properties = _com.ice_getCommunicator().getProperties().ice_clone_(); initData.logger = _logger; initData.properties.setProperty("Ice.ACM.Timeout", "1"); if(_clientACMTimeout >= 0) { initData.properties.setProperty("Ice.ACM.Client.Timeout", _clientACMTimeout.ToString()); } if(_clientACMClose >= 0) { initData.properties.setProperty("Ice.ACM.Client.Close", _clientACMClose.ToString()); } if(_clientACMHeartbeat >= 0) { initData.properties.setProperty("Ice.ACM.Client.Heartbeat", _clientACMHeartbeat.ToString()); } //initData.properties.setProperty("Ice.Trace.Protocol", "2"); //initData.properties.setProperty("Ice.Trace.Network", "2"); _communicator = Ice.Util.initialize(initData); _thread = new Thread(this.run); } public void start() { _thread.Start(); } public void destroy() { _adapter.deactivate(); _communicator.destroy(); } public void join() { System.Console.Out.Write("testing " + _name + "... "); System.Console.Out.Flush(); _logger.start(); _thread.Join(); if(_msg == null) { System.Console.Out.WriteLine("ok"); } else { System.Console.Out.WriteLine("failed! " + _msg); throw new System.Exception(); } } public void run() { TestIntfPrx proxy = TestIntfPrxHelper.uncheckedCast(_communicator.stringToProxy( _adapter.getTestIntf().ToString())); try { proxy.ice_getConnection().setCallback(this); runTestCase(_adapter, proxy); } catch(Exception ex) { _msg = "unexpected exception:\n" + ex.ToString(); } } public void heartbeat(Ice.Connection con) { lock(this) { ++_heartbeat; } } public void closed(Ice.Connection con) { lock(this) { _closed = true; Monitor.Pulse(this); } } public void waitForClosed() { lock(this) { long now = IceInternal.Time.currentMonotonicTimeMillis(); while(!_closed) { Monitor.Wait(this, 1000); if(IceInternal.Time.currentMonotonicTimeMillis() - now > 1000) { System.Diagnostics.Debug.Assert(false); // Waited for more than 1s for close, something's wrong. throw new System.Exception(); } } } } public abstract void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy); public void setClientACM(int timeout, int close, int heartbeat) { _clientACMTimeout = timeout; _clientACMClose = close; _clientACMHeartbeat = heartbeat; } public void setServerACM(int timeout, int close, int heartbeat) { _serverACMTimeout = timeout; _serverACMClose = close; _serverACMHeartbeat = heartbeat; } private string _name; private RemoteCommunicatorPrx _com; private string _msg; private LoggerI _logger; private System.Threading.Thread _thread; private Ice.Communicator _communicator; private RemoteObjectAdapterPrx _adapter; private int _clientACMTimeout; private int _clientACMClose; private int _clientACMHeartbeat; private int _serverACMTimeout; private int _serverACMClose; private int _serverACMHeartbeat; protected int _heartbeat; protected bool _closed; }; public class AllTests : TestCommon.TestApp { class InvocationHeartbeatTest : TestCase { public InvocationHeartbeatTest(RemoteCommunicatorPrx com) : base("invocation heartbeat", com) { } public override void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy) { proxy.sleep(2); lock(this) { test(_heartbeat >= 2); } } }; class InvocationHeartbeatOnHoldTest : TestCase { public InvocationHeartbeatOnHoldTest(RemoteCommunicatorPrx com) : base("invocation with heartbeat on hold", com) { // Use default ACM configuration. } public override void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy) { try { // When the OA is put on hold, connections shouldn't // send heartbeats, the invocation should therefore // fail. proxy.sleepAndHold(10); test(false); } catch(Ice.ConnectionTimeoutException) { adapter.activate(); proxy.interruptSleep(); waitForClosed(); } } }; class InvocationNoHeartbeatTest : TestCase { public InvocationNoHeartbeatTest(RemoteCommunicatorPrx com) : base("invocation with no heartbeat", com) { setServerACM(1, 2, 0); // Disable heartbeat on invocations } public override void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy) { try { // Heartbeats are disabled on the server, the // invocation should fail since heartbeats are // expected. proxy.sleep(10); test(false); } catch(Ice.ConnectionTimeoutException) { proxy.interruptSleep(); waitForClosed(); lock(this) { test(_heartbeat == 0); } } } }; class InvocationHeartbeatCloseOnIdleTest : TestCase { public InvocationHeartbeatCloseOnIdleTest(RemoteCommunicatorPrx com) : base("invocation with no heartbeat and close on idle", com) { setClientACM(1, 1, 0); // Only close on idle. setServerACM(1, 2, 0); // Disable heartbeat on invocations } public override void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy) { // No close on invocation, the call should succeed this // time. proxy.sleep(2); lock(this) { test(_heartbeat == 0); test(!_closed); } } }; class CloseOnIdleTest : TestCase { public CloseOnIdleTest(RemoteCommunicatorPrx com) : base("close on idle", com) { setClientACM(1, 1, 0); // Only close on idle } public override void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy) { Thread.Sleep(1500); // Idle for 1.5 second waitForClosed(); lock(this) { test(_heartbeat == 0); } } }; class CloseOnInvocationTest : TestCase { public CloseOnInvocationTest(RemoteCommunicatorPrx com) : base("close on invocation", com) { setClientACM(1, 2, 0); // Only close on invocation } public override void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy) { Thread.Sleep(1500); // Idle for 1.5 second lock(this) { test(_heartbeat == 0); test(!_closed); } } }; class CloseOnIdleAndInvocationTest : TestCase { public CloseOnIdleAndInvocationTest(RemoteCommunicatorPrx com) : base("close on idle and invocation", com) { setClientACM(1, 3, 0); // Only close on idle and invocation } public override void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy) { // // Put the adapter on hold. The server will not respond to // the graceful close. This allows to test whether or not // the close is graceful or forceful. // adapter.hold(); Thread.Sleep(1500); // Idle for 1.5 second lock(this) { test(_heartbeat == 0); test(!_closed); // Not closed yet because of graceful close. } adapter.activate(); Thread.Sleep(500); waitForClosed(); } }; class ForcefulCloseOnIdleAndInvocationTest : TestCase { public ForcefulCloseOnIdleAndInvocationTest(RemoteCommunicatorPrx com) : base("forceful close on idle and invocation", com) { setClientACM(1, 4, 0); // Only close on idle and invocation } public override void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy) { adapter.hold(); Thread.Sleep(1500); // Idle for 1.5 second waitForClosed(); lock(this) { test(_heartbeat == 0); } } }; class HeartbeatOnIdleTest : TestCase { public HeartbeatOnIdleTest(RemoteCommunicatorPrx com) : base("heartbeat on idle", com) { setServerACM(1, -1, 2); // Enable server heartbeats. } public override void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy) { Thread.Sleep(2000); lock(this) { test(_heartbeat >= 3); } } }; class HeartbeatAlwaysTest : TestCase { public HeartbeatAlwaysTest(RemoteCommunicatorPrx com) : base("heartbeat always", com) { setServerACM(1, -1, 3); // Enable server heartbeats. } public override void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy) { for(int i = 0; i < 12; i++) { proxy.ice_ping(); Thread.Sleep(200); } lock(this) { test(_heartbeat >= 3); } } }; class SetACMTest : TestCase { public SetACMTest(RemoteCommunicatorPrx com) : base("setACM/getACM", com) { setClientACM(15, 4, 0); } public override void runTestCase(RemoteObjectAdapterPrx adapter, TestIntfPrx proxy) { Ice.ACM acm; acm = proxy.ice_getCachedConnection().getACM(); test(acm.timeout == 15); test(acm.close == Ice.ACMClose.CloseOnIdleForceful); test(acm.heartbeat == Ice.ACMHeartbeat.HeartbeatOff); proxy.ice_getCachedConnection().setACM(Ice.Util.None, Ice.Util.None, Ice.Util.None); acm = proxy.ice_getCachedConnection().getACM(); test(acm.timeout == 15); test(acm.close == Ice.ACMClose.CloseOnIdleForceful); test(acm.heartbeat == Ice.ACMHeartbeat.HeartbeatOff); proxy.ice_getCachedConnection().setACM(1, Ice.ACMClose.CloseOnInvocationAndIdle, Ice.ACMHeartbeat.HeartbeatAlways); acm = proxy.ice_getCachedConnection().getACM(); test(acm.timeout == 1); test(acm.close == Ice.ACMClose.CloseOnInvocationAndIdle); test(acm.heartbeat == Ice.ACMHeartbeat.HeartbeatAlways); proxy.waitForHeartbeat(2); } }; #if SILVERLIGHT override public void run(Ice.Communicator communicator) #else public static void allTests(Ice.Communicator communicator) #endif { string @ref = "communicator:default -p 12010"; RemoteCommunicatorPrx com = RemoteCommunicatorPrxHelper.uncheckedCast(communicator.stringToProxy(@ref)); List tests = new List(); tests.Add(new InvocationHeartbeatTest(com)); tests.Add(new InvocationHeartbeatOnHoldTest(com)); tests.Add(new InvocationNoHeartbeatTest(com)); tests.Add(new InvocationHeartbeatCloseOnIdleTest(com)); tests.Add(new CloseOnIdleTest(com)); tests.Add(new CloseOnInvocationTest(com)); tests.Add(new CloseOnIdleAndInvocationTest(com)); tests.Add(new ForcefulCloseOnIdleAndInvocationTest(com)); tests.Add(new HeartbeatOnIdleTest(com)); tests.Add(new HeartbeatAlwaysTest(com)); tests.Add(new SetACMTest(com)); foreach(TestCase test in tests) { test.init(); } foreach(TestCase test in tests) { test.start(); } foreach(TestCase test in tests) { test.join(); } foreach(TestCase test in tests) { test.destroy(); } System.Console.Out.Write("shutting down... "); System.Console.Out.Flush(); com.shutdown(); System.Console.WriteLine("ok"); } }