// Copyright 2020-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using Shouldly; using ZB.MOM.NatsNet.Server; namespace ZB.MOM.NatsNet.Server.Tests.Foundation; /// /// Tests for and . /// Mirrors server/errors_test.go: TestErrCtx (ID 297) and TestErrCtxWrapped (ID 298). /// public sealed class ServerErrorsTests { [Fact] public void ErrCtx_ShouldPreserveOriginalMessageAndAddContext() { // Mirror: TestErrCtx var ctx = "Extra context information"; var e = ErrorContextHelper.NewErrorCtx(ServerErrors.ErrWrongGateway, "{0}", ctx); // Message should match the underlying error. e.Message.ShouldBe(ServerErrors.ErrWrongGateway.Message); // Must not be reference-equal to the sentinel. e.ShouldNotBeSameAs(ServerErrors.ErrWrongGateway); // ErrorIs should find the sentinel in the chain. ErrorContextHelper.ErrorIs(e, ServerErrors.ErrWrongGateway).ShouldBeTrue(); // UnpackIfErrorCtx on a non-ctx error returns Message unchanged. ErrorContextHelper.UnpackIfErrorCtx(ServerErrors.ErrWrongGateway) .ShouldBe(ServerErrors.ErrWrongGateway.Message); // UnpackIfErrorCtx should start with the original error message. var trace = ErrorContextHelper.UnpackIfErrorCtx(e); trace.ShouldStartWith(ServerErrors.ErrWrongGateway.Message); // And end with the context string. trace.ShouldEndWith(ctx); } [Fact] public void ErrCtxWrapped_ShouldContainAllContextLayers() { // Mirror: TestErrCtxWrapped var ctxO = "Original Ctx"; var eO = ErrorContextHelper.NewErrorCtx(ServerErrors.ErrWrongGateway, "{0}", ctxO); var ctx = "Extra context information"; var e = ErrorContextHelper.NewErrorCtx(eO, "{0}", ctx); // Message should still match the underlying error. e.Message.ShouldBe(ServerErrors.ErrWrongGateway.Message); // Must not be reference-equal to the sentinel. e.ShouldNotBeSameAs(ServerErrors.ErrWrongGateway); // ErrorIs should walk the chain. ErrorContextHelper.ErrorIs(e, ServerErrors.ErrWrongGateway).ShouldBeTrue(); // UnpackIfErrorCtx on a non-ctx error returns Message unchanged. ErrorContextHelper.UnpackIfErrorCtx(ServerErrors.ErrWrongGateway) .ShouldBe(ServerErrors.ErrWrongGateway.Message); var trace = ErrorContextHelper.UnpackIfErrorCtx(e); // Must start with the original error. trace.ShouldStartWith(ServerErrors.ErrWrongGateway.Message); // Must end with the outermost context. trace.ShouldEndWith(ctx); // Must also contain the inner context. trace.ShouldContain(ctxO); } }