File: MockCommunicationObject.cs
Web Access
Project: src\src\System.Private.ServiceModel\tests\Common\Unit\UnitTests.Common.csproj (UnitTests.Common)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
 
// Mock CommunicationObject allows caller to provide delegate to intercept
// every abstract and virtual method.  Each has a corresponding Defaultxxx()
// method that does what the default Communication object would do, allowing
// the caller to do processing before and after the default behavior.
public class MockCommunicationObject : CommunicationObject, IMockCommunicationObject
{
    public MockCommunicationObject()
    {
        OpenAsyncResult = new MockAsyncResult();
        CloseAsyncResult = new MockAsyncResult();
 
        // Each overrideable method has a delegate property that
        // can be set to override it, please a default handler.
 
        // All the abstracts
        DefaultCloseTimeoutOverride = DefaultDefaultCloseTimeout;
        DefaultOpenTimeoutOverride = DefaultDefaultOpenTimeout;
 
        OnAbortOverride = DefaultOnAbort;
        OnOpenOverride = DefaultOnOpen;
        OnCloseOverride = DefaultOnClose;
 
        OnBeginOpenOverride = DefaultOnBeginOpen;
        OnEndOpenOverride = DefaultOnEndOpen;
 
        OnBeginCloseOverride = DefaultOnBeginClose;
        OnEndCloseOverride = DefaultOnEndClose;
 
        // All the virtuals
        OnOpeningOverride = DefaultOnOpening;
        OnOpenedOverride = DefaultOnOpened;
        OnClosingOverride = DefaultOnClosing;
        OnClosedOverride = DefaultOnClosed;
        OnFaultedOverride = DefaultOnFaulted;
    }
 
    public MockAsyncResult OpenAsyncResult { get; set; }
    public MockAsyncResult CloseAsyncResult { get; set; }
 
    // Abstract overrides
    public Func<TimeSpan> DefaultCloseTimeoutOverride { get; set; }
    public Func<TimeSpan> DefaultOpenTimeoutOverride { get; set; }
    public Action OnAbortOverride { get; set; }
    public Func<TimeSpan, AsyncCallback, object, IAsyncResult> OnBeginCloseOverride { get; set; }
    public Func<TimeSpan, AsyncCallback, object, IAsyncResult> OnBeginOpenOverride { get; set; }
    public Action<TimeSpan> OnOpenOverride { get; set; }
    public Action<TimeSpan> OnCloseOverride { get; set; }
    public Action<IAsyncResult> OnEndCloseOverride { get; set; }
    public Action<IAsyncResult> OnEndOpenOverride { get; set; }
 
    // Virtual overrides
    public Action OnOpeningOverride { get; set; }
    public Action OnOpenedOverride { get; set; }
    public Action OnClosingOverride { get; set; }
    public Action OnClosedOverride { get; set; }
    public Action OnFaultedOverride { get; set; }
 
    protected override TimeSpan DefaultCloseTimeout
    {
        get
        {
            return DefaultCloseTimeoutOverride();
        }
    }
 
    public TimeSpan DefaultDefaultCloseTimeout()
    {
        return TimeSpan.FromSeconds(30);
    }
 
    protected override TimeSpan DefaultOpenTimeout
    {
        get
        {
            return DefaultOpenTimeoutOverride();
        }
    }
 
    public TimeSpan DefaultDefaultOpenTimeout()
    {
        return TimeSpan.FromSeconds(30);
    }
 
    protected override void OnAbort()
    {
        OnAbortOverride();
    }
 
    public void DefaultOnAbort()
    {
        // abstract -- no base to call
    }
 
    protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
    {
        return OnBeginCloseOverride(timeout, callback, state);
    }
 
    public IAsyncResult DefaultOnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
    {
        // Modify the placeholder async result we already instantiated.
        CloseAsyncResult.Callback = callback;
        CloseAsyncResult.AsyncState = state;
 
        // The mock always Completes the IAsyncResult before handing it back.
        // This is done because the sync path has no access to this IAsyncResult
        // that happens behind the scenes.
        CloseAsyncResult.Complete();
 
        return CloseAsyncResult;
        // abstract -- no base to call
    }
 
    protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
    {
        return OnBeginOpenOverride(timeout, callback, state);
        // abstract -- no base to call
    }
 
    public IAsyncResult DefaultOnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
    {
        // Modify the placeholder async result we already instantiated.
        OpenAsyncResult.Callback = callback;
        OpenAsyncResult.AsyncState = state;
 
        // The mock always Completes the IAsyncResult before handing it back.
        // This is done because the sync path has no access to this IAsyncResult
        // that happens behind the scenes.
        OpenAsyncResult.Complete();
 
        return OpenAsyncResult;
        // abstract -- no base to call
    }
 
    protected override void OnClose(TimeSpan timeout)
    {
        OnCloseOverride(timeout);
    }
 
    public void DefaultOnClose(TimeSpan timeout)
    {
        // abstract -- no base to call
    }
 
    protected override void OnEndClose(IAsyncResult result)
    {
        OnEndCloseOverride(result);
    }
 
    public void DefaultOnEndClose(IAsyncResult result)
    {
        ((MockAsyncResult)result).Complete();
        // abstract -- no base to call
    }
 
    protected override void OnEndOpen(IAsyncResult result)
    {
        OnEndOpenOverride(result);
    }
 
    public void DefaultOnEndOpen(IAsyncResult result)
    {
        ((MockAsyncResult)result).Complete();
        // abstract -- no base to call
    }
 
    protected override void OnOpen(TimeSpan timeout)
    {
        OnOpenOverride(timeout);
    }
 
    public void DefaultOnOpen(TimeSpan timeout)
    {
        // abstract -- no base to call
    }
 
    // Virtuals
    protected override void OnOpening()
    {
        OnOpeningOverride();
    }
 
    public void DefaultOnOpening()
    {
        base.OnOpening();
    }
 
    protected override void OnOpened()
    {
        OnOpenedOverride();
    }
 
    public void DefaultOnOpened()
    {
        base.OnOpened();
    }
 
    protected override void OnClosing()
    {
        OnClosingOverride();
    }
 
    public void DefaultOnClosing()
    {
        base.OnClosing();
    }
 
    protected override void OnClosed()
    {
        OnClosedOverride();
    }
 
    public void DefaultOnClosed()
    {
        base.OnClosed();
    }
 
    protected override void OnFaulted()
    {
        OnFaultedOverride();
    }
 
    public void DefaultOnFaulted()
    {
        base.OnFaulted();
    }
 
    #region helpers
 
    public static void InterceptAllOpenMethods(IMockCommunicationObject mco, List<string> methodsCalled)
    {
        mco.OnOpeningOverride = () =>
        {
            methodsCalled.Add("OnOpening");
            mco.DefaultOnOpening();
        };
 
        mco.OnOpenOverride = (TimeSpan t) =>
        {
            methodsCalled.Add("OnOpen");
            mco.DefaultOnOpen(t);
        };
 
        mco.OnBeginOpenOverride = (TimeSpan t, AsyncCallback c, object s) =>
        {
            methodsCalled.Add("OnBeginOpen");
            return mco.DefaultOnBeginOpen(t, c, s);
        };
 
        mco.OnOpenedOverride = () =>
        {
            methodsCalled.Add("OnOpened");
            mco.DefaultOnOpened();
        };
    }
 
    // This helper will override all the open methods of the MockCommunicationObject
    // and record their names into the provided list in the order they are called.
    public static void InterceptAllCloseMethods(IMockCommunicationObject mco, List<string> methodsCalled)
    {
        mco.OnClosingOverride = () =>
        {
            methodsCalled.Add("OnClosing");
            mco.DefaultOnClosing();
        };
 
        mco.OnCloseOverride = (TimeSpan t) =>
        {
            methodsCalled.Add("OnClose");
            mco.DefaultOnClose(t);
        };
 
        mco.OnBeginCloseOverride = (TimeSpan t, AsyncCallback c, object s) =>
        {
            methodsCalled.Add("OnBeginClose");
            return mco.DefaultOnBeginClose(t, c, s);
        };
 
        mco.OnClosedOverride = () =>
        {
            methodsCalled.Add("OnClosed");
            mco.DefaultOnClosed();
        };
 
        // The OnAbort is considered one of the methods associated with close.
        mco.OnAbortOverride = () =>
        {
            methodsCalled.Add("OnAbort");
            mco.DefaultOnAbort();
        };
    }
 
    // Intercepts all the events expected to fire during an open
    public static void InterceptAllOpenEvents(IMockCommunicationObject mco, List<string> eventsFired)
    {
        mco.Opening += (s, ea) => eventsFired.Add("Opening");
        mco.Opened += (s, ea) => eventsFired.Add("Opened");
    }
 
    // Intercepts all the events expected to fire during a close
    public static void InterceptAllCloseEvents(IMockCommunicationObject mco, List<string> eventsFired)
    {
        mco.Closing += (s, ea) => eventsFired.Add("Closing");
        mco.Closed += (s, ea) => eventsFired.Add("Closed");
    }
 
    // Intercepts all the open and close methods in MockCommunicationObject
    // and records the CommunicationState before and after the default code executes,
    public static void InterceptAllStateChanges(IMockCommunicationObject mco, CommunicationStateData data)
    {
        // Immediately capture the current state after initial creation
        data.StateAfterCreate = mco.State;
 
        mco.OnOpeningOverride = () =>
        {
            data.StateEnterOnOpening = mco.State;
            mco.DefaultOnOpening();
            data.StateLeaveOnOpening = mco.State;
        };
 
        mco.OnOpenOverride = (TimeSpan t) =>
        {
            data.StateEnterOnOpen = mco.State;
            mco.DefaultOnOpen(t);
            data.StateLeaveOnOpen = mco.State;
        };
 
        mco.OnBeginOpenOverride = (TimeSpan t, AsyncCallback c, object s) =>
        {
            data.StateEnterOnBeginOpen = mco.State;
            IAsyncResult result = mco.DefaultOnBeginOpen(t, c, s);
            data.StateLeaveOnBeginOpen = mco.State;
            return result;
        };
 
        mco.OnOpenedOverride = () =>
        {
            data.StateEnterOnOpened = mco.State;
            mco.DefaultOnOpened();
            data.StateLeaveOnOpened = mco.State;
        };
 
        mco.OnClosingOverride = () =>
        {
            data.StateEnterOnClosing = mco.State;
            mco.DefaultOnClosing();
            data.StateLeaveOnClosing = mco.State;
        };
 
        mco.OnCloseOverride = (TimeSpan t) =>
        {
            data.StateEnterOnClose = mco.State;
            mco.DefaultOnClose(t);
            data.StateLeaveOnClose = mco.State;
        };
 
        mco.OnBeginCloseOverride = (TimeSpan t, AsyncCallback c, object s) =>
        {
            data.StateEnterOnBeginClose = mco.State;
            IAsyncResult result = mco.DefaultOnBeginClose(t, c, s);
            data.StateLeaveOnBeginClose = mco.State;
            return result;
        };
 
        mco.OnClosedOverride = () =>
        {
            data.StateEnterOnClosed = mco.State;
            mco.DefaultOnClosed();
            data.StateLeaveOnClosed = mco.State;
        };
 
        #endregion helpers
    }
}
 
public class CommunicationStateData
{
    public CommunicationState StateAfterCreate { get; set; }
    public CommunicationState StateEnterOnOpening { get; set; }
    public CommunicationState StateLeaveOnOpening { get; set; }
    public CommunicationState StateEnterOnOpen { get; set; }
    public CommunicationState StateLeaveOnOpen { get; set; }
    public CommunicationState StateEnterOnBeginOpen { get; set; }
    public CommunicationState StateLeaveOnBeginOpen { get; set; }
    public CommunicationState StateEnterOnOpened { get; set; }
    public CommunicationState StateLeaveOnOpened { get; set; }
 
    public CommunicationState StateEnterOnClosing { get; set; }
    public CommunicationState StateLeaveOnClosing { get; set; }
    public CommunicationState StateEnterOnClose { get; set; }
    public CommunicationState StateLeaveOnClose { get; set; }
    public CommunicationState StateEnterOnBeginClose { get; set; }
    public CommunicationState StateLeaveOnBeginClose { get; set; }
    public CommunicationState StateEnterOnClosed { get; set; }
    public CommunicationState StateLeaveOnClosed { get; set; }
}