< Summary

Information
Class: Ice.CurrentExtensions
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/CurrentExtensions.cs
Tag: 71_18251537082
Line coverage
86%
Covered lines: 86
Uncovered lines: 13
Coverable lines: 99
Total lines: 278
Line coverage: 86.8%
Branch coverage
95%
Covered branches: 57
Total branches: 60
Branch coverage: 95%
Method coverage
100%
Covered methods: 7
Total methods: 7
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
checkNonIdempotent(...)50%2.5250%
createOutgoingResponse<TResult>(...)50%2.11270%
createEmptyOutgoingResponse(...)100%2.21262.5%
createOutgoingResponse(...)100%10.81080%
createOutgoingResponse(...)100%1.13150%
createOutgoingResponseCore()97.62%4242100%
startReplyStream(...)100%22100%

File(s)

/home/runner/work/ice/ice/csharp/src/Ice/CurrentExtensions.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5using Ice.Internal;
 6using System.Diagnostics;
 7
 8namespace Ice;
 9
 10/// <summary>
 11/// Provides extension methods for <see cref="Current"/>.
 12/// </summary>
 13public static class CurrentExtensions
 14{
 15    /// <summary>Makes sure the operation mode of an incoming request is not idempotent.</summary>
 16    /// <param name="current">The current object of the corresponding incoming request.</param>
 17    /// <exception cref="MarshalException">Thrown when the request's operation mode is
 18    /// <see cref="OperationMode.Idempotent" /> or <see cref="OperationMode.Nonmutating" />.</exception>
 19    /// <remarks>The generated code calls this method to ensure that when an operation's mode is not idempotent
 20    /// (locally), the incoming request's operation mode is not idempotent.</remarks>
 21    public static void checkNonIdempotent(this Current current)
 22    {
 123        if (current.mode != OperationMode.Normal)
 24        {
 025            throw new MarshalException(
 026                $"Operation mode mismatch for operation '{current.operation}': received {current.mode} for non-idempoten
 27        }
 128    }
 29
 30    /// <summary>
 31    /// Creates an outgoing response with reply status <see cref="ReplyStatus.Ok"/>.
 32    /// </summary>
 33    /// <typeparam name="TResult">The type of result.</typeparam>
 34    /// <param name="current">The current object of the corresponding incoming request.</param>
 35    /// <param name="result">The result to marshal into the response payload.</param>
 36    /// <param name="marshal">The action that marshals result into an output stream.</param>
 37    /// <param name="formatType">The class format.</param>
 38    /// <returns>A new outgoing response.</returns>
 39    public static OutgoingResponse createOutgoingResponse<TResult>(
 40        this Current current,
 41        TResult result,
 42        Action<OutputStream, TResult> marshal,
 43        FormatType? formatType = null)
 44    {
 145        OutputStream ostr = current.startReplyStream();
 146        if (current.requestId != 0)
 47        {
 48            try
 49            {
 150                ostr.startEncapsulation(current.encoding, formatType);
 151                marshal(ostr, result);
 152                ostr.endEncapsulation();
 153                return new OutgoingResponse(ostr);
 54            }
 055            catch (System.Exception exception)
 56            {
 057                return current.createOutgoingResponse(exception);
 58            }
 59        }
 60        else
 61        {
 62            Debug.Fail("A one-way request cannot return a response");
 063            return new OutgoingResponse(ostr);
 64        }
 165    }
 66
 67    /// <summary>
 68    /// Creates an empty outgoing response with reply status <see cref="ReplyStatus.Ok"/>.
 69    /// </summary>
 70    /// <param name="current">The current object of the corresponding incoming request.</param>
 71    /// <returns>An outgoing response with an empty payload.</returns>
 72    public static OutgoingResponse createEmptyOutgoingResponse(this Current current)
 73    {
 174        OutputStream ostr = current.startReplyStream();
 175        if (current.requestId != 0)
 76        {
 77            try
 78            {
 179                ostr.writeEmptyEncapsulation(current.encoding);
 180            }
 081            catch (System.Exception ex)
 82            {
 083                return current.createOutgoingResponse(ex);
 84            }
 85        }
 186        return new OutgoingResponse(ostr);
 087    }
 88
 89    /// <summary>
 90    /// Creates an outgoing response with the specified payload.
 91    /// </summary>
 92    /// <param name="current">The current object of the corresponding incoming request.</param>
 93    /// <param name="ok">When true, the reply status of the response is <see cref="ReplyStatus.Ok" />; otherwise, it's
 94    /// <see cref="ReplyStatus.UserException" />.</param>
 95    /// <param name="encapsulation">The payload of the response.</param>
 96    /// <returns>A new outgoing response.</returns>
 97    public static OutgoingResponse createOutgoingResponse(this Current current, bool ok, byte[] encapsulation)
 98    {
 99        // For compatibility with the Ice 3.7 and earlier.
 1100        encapsulation ??= [];
 101
 1102        OutputStream ostr = current.startReplyStream(ok ? ReplyStatus.Ok : ReplyStatus.UserException);
 103
 1104        if (current.requestId != 0)
 105        {
 106            try
 107            {
 1108                if (encapsulation.Length > 0)
 109                {
 1110                    ostr.writeEncapsulation(encapsulation);
 111                }
 112                else
 113                {
 1114                    ostr.writeEmptyEncapsulation(current.encoding);
 115                }
 1116            }
 0117            catch (System.Exception ex)
 118            {
 0119                return current.createOutgoingResponse(ex);
 120            }
 121        }
 1122        return new OutgoingResponse(
 1123            replyStatus: ok ? ReplyStatus.Ok : ReplyStatus.UserException,
 1124            exceptionId: null,
 1125            exceptionDetails: null,
 1126            ostr);
 0127    }
 128
 129    /// <summary>
 130    /// Creates an outgoing response that marshals an exception.
 131    /// </summary>
 132    /// <param name="current">The current object of the corresponding incoming request.</param>
 133    /// <param name="exception">The exception to marshal into the response payload.</param>
 134    /// <returns>A new outgoing response.</returns>
 135    public static OutgoingResponse createOutgoingResponse(this Current current, System.Exception exception)
 136    {
 137        try
 138        {
 1139            return createOutgoingResponseCore(exception);
 140        }
 0141        catch (System.Exception ex)
 142        {
 143            // Try a second time with the marshal exception. This should not fail.
 0144            return createOutgoingResponseCore(ex);
 145        }
 146
 147        OutgoingResponse createOutgoingResponseCore(System.Exception exc)
 148        {
 149            OutputStream ostr;
 150
 1151            if (current.requestId != 0)
 152            {
 153                // The default class format doesn't matter since we always encode user exceptions in Sliced format.
 1154                ostr = new OutputStream(Util.currentProtocolEncoding);
 1155                ostr.writeBlob(Protocol.replyHdr);
 1156                ostr.writeInt(current.requestId);
 157            }
 158            else
 159            {
 1160                ostr = new OutputStream();
 161            }
 162
 163            ReplyStatus replyStatus;
 164            string? exceptionId;
 1165            string? dispatchExceptionMessage = null;
 166
 167            switch (exc)
 168            {
 169                case UserException ex:
 1170                    exceptionId = null;
 1171                    replyStatus = ReplyStatus.UserException;
 172
 1173                    if (current.requestId != 0)
 174                    {
 1175                        ReplyStatusHelper.write(ostr, replyStatus);
 1176                        ostr.startEncapsulation(current.encoding, FormatType.SlicedFormat);
 1177                        ostr.writeException(ex);
 1178                        ostr.endEncapsulation();
 179                    }
 1180                    break;
 181
 182                case DispatchException ex:
 1183                    exceptionId = ex.ice_id();
 1184                    replyStatus = ex.replyStatus;
 1185                    dispatchExceptionMessage = ex.Message;
 1186                    break;
 187
 188                case LocalException ex:
 1189                    exceptionId = ex.ice_id();
 1190                    replyStatus = ReplyStatus.UnknownLocalException;
 1191                    break;
 192
 193                default:
 1194                    replyStatus = ReplyStatus.UnknownException;
 1195                    exceptionId = exc.GetType().FullName ?? "System.Exception";
 196                    break;
 197            }
 198
 1199            if (replyStatus > ReplyStatus.UserException && current.requestId != 0) // two-way, so we marshal a reply
 200            {
 201                // We can't use ReplyStatusHelper to marshal a possibly unknown reply status value.
 1202                ostr.writeByte((byte)replyStatus);
 203
 1204                if (replyStatus is ReplyStatus.ObjectNotExist or
 1205                    ReplyStatus.FacetNotExist or
 1206                    ReplyStatus.OperationNotExist)
 207                {
 1208                    var rfe = exc as RequestFailedException; // can be null
 209
 1210                    Identity id = rfe?.id ?? new Identity();
 1211                    string facet = rfe?.facet ?? "";
 1212                    if (id.name.Length == 0)
 213                    {
 1214                        id = current.id;
 1215                        facet = current.facet;
 216                    }
 1217                    string operation = rfe?.operation ?? "";
 1218                    if (operation.Length == 0)
 219                    {
 1220                        operation = current.operation;
 221                    }
 222
 1223                    Identity.ice_write(ostr, id);
 224
 1225                    if (facet.Length == 0)
 226                    {
 1227                        ostr.writeStringSeq([]);
 228                    }
 229                    else
 230                    {
 1231                        ostr.writeStringSeq([facet]);
 232                    }
 1233                    ostr.writeString(operation);
 234                    // and we don't use the dispatchExceptionMessage.
 235                }
 236                else
 237                {
 238                    // If the exception is a DispatchException, we keep its message as-is; otherwise, we create a custom
 239                    // message. This message doesn't include the stack trace.
 1240                    dispatchExceptionMessage ??= $"Dispatch failed with {exceptionId}: {exc.Message}";
 1241                    ostr.writeString(dispatchExceptionMessage);
 242                }
 243            }
 244
 1245            return new OutgoingResponse(
 1246                replyStatus,
 1247                exceptionId,
 1248                replyStatus > ReplyStatus.UserException ? exc.ToString() : null,
 1249                ostr);
 250        }
 1251    }
 252
 253    /// <summary>
 254    /// Starts the output stream for a reply, with everything up to and including the reply status. When the request ID
 255    /// is 0 (one-way request), the returned output stream is empty.
 256    /// </summary>
 257    /// <param name="current">The current object of the corresponding incoming request.</param>
 258    /// <param name="replyStatus">The reply status.</param>
 259    /// <returns>The new output stream.</returns>
 260    public static OutputStream startReplyStream(this Current current, ReplyStatus replyStatus = ReplyStatus.Ok)
 261    {
 1262        if (current.requestId == 0)
 263        {
 1264            return new OutputStream();
 265        }
 266        else
 267        {
 1268            var ostr = new OutputStream(
 1269                Util.currentProtocolEncoding,
 1270                current.adapter.getCommunicator().instance.defaultsAndOverrides().defaultFormat);
 271
 1272            ostr.writeBlob(Protocol.replyHdr);
 1273            ostr.writeInt(current.requestId);
 1274            ReplyStatusHelper.write(ostr, replyStatus);
 1275            return ostr;
 276        }
 277    }
 278}