<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using Gigya.Common.Application.HttpService.Client;
using Gigya.Common.Contracts.Exceptions;
using Gigya.Microdot.SharedLogic.Exceptions;
using Gigya.Microdot.SharedLogic.Utils;
using Ninject;
using NUnit.Framework;

using Shouldly;

namespace Gigya.Microdot.UnitTests.ServiceProxyTests
{
    public class JsonExceptionSerializerTests : UpdatableConfigTests
    {
        private JsonExceptionSerializer ExceptionSerializer { get; set; }

        public override void Setup()
        {
            
        }

        public override void OneTimeSetUp()
        {
            base.OneTimeSetUp();
            ExceptionSerializer = _unitTestingKernel.Get<JsonExceptionSerializer>();
            Task t = ChangeConfig<StackTraceEnhancerSettings>(new[]
            {
                new KeyValuePair<string, string>("StackTraceEnhancerSettings.RegexReplacements.TidyAsyncLocalFunctionNames.Pattern",
                    @"\.<>c__DisplayClass(?:\d+)_(?:\d+)(?:`\d)?\.<<(\w+)>g__(\w+)\|?\d>d.MoveNext\(\)"),
                new KeyValuePair<string, string>("StackTraceEnhancerSettings.RegexReplacements.TidyAsyncLocalFunctionNames.Replacement",
                    @".$1.$2(async)")
            });
            t.Wait();
        }

        protected override Action<IKernel> AdditionalBindings()
        {
            return null;
        }

        [Test]
        public void RequestException_RoundTrip_IsIdentical()
        {
            var expected = new RequestException("message").ThrowAndCatch();
            var json = ExceptionSerializer.Serialize(expected);

            var actual = ExceptionSerializer.Deserialize(json);

            actual.ShouldBeOfType<RequestException>();
            actual.Message.ShouldBe(expected.Message);
            actual.StackTrace.ShouldNotBeNullOrEmpty();
        }

        [Test]
        public void CustomerFacingException_RoundTrip_IsIdentical()
        {
            var expected = new RequestException("message", 30000).ThrowAndCatch();
            var json = ExceptionSerializer.Serialize(expected);

            var actual = (RequestException)ExceptionSerializer.Deserialize(json);

            actual.ShouldBeOfType<RequestException>();
            actual.Message.ShouldBe(expected.Message);
            actual.ErrorCode.ShouldBe(expected.ErrorCode);
            actual.StackTrace.ShouldNotBeNullOrEmpty();
        }

        [Test]
        public void ExceptionTypeNotAvailable_RoundTrip_FallsBackToAvailableType()
        {<commit_msg>Add tests for breadcrumbs serialization<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using Gigya.Common.Application.HttpService.Client;
using Gigya.Common.Contracts.Exceptions;
using Gigya.Microdot.SharedLogic.Exceptions;
using Gigya.Microdot.SharedLogic.Utils;
using Ninject;
using NUnit.Framework;

using Shouldly;

namespace Gigya.Microdot.UnitTests.ServiceProxyTests
{
    public class JsonExceptionSerializerTests : UpdatableConfigTests
    {
        private JsonExceptionSerializer ExceptionSerializer { get; set; }

        public override void Setup()
        {
            
        }

        public override void OneTimeSetUp()
        {
            base.OneTimeSetUp();
            ExceptionSerializer = _unitTestingKernel.Get<JsonExceptionSerializer>();
            Task t = ChangeConfig<StackTraceEnhancerSettings>(new[]
            {
                new KeyValuePair<string, string>("StackTraceEnhancerSettings.RegexReplacements.TidyAsyncLocalFunctionNames.Pattern",
                    @"\.<>c__DisplayClass(?:\d+)_(?:\d+)(?:`\d)?\.<<(\w+)>g__(\w+)\|?\d>d.MoveNext\(\)"),
                new KeyValuePair<string, string>("StackTraceEnhancerSettings.RegexReplacements.TidyAsyncLocalFunctionNames.Replacement",
                    @".$1.$2(async)")
            });
            t.Wait();
        }

        protected override Action<IKernel> AdditionalBindings()
        {
            return null;
        }

        [Test]
        public void RequestException_RoundTrip_IsIdentical()
        {
            var expected = new RequestException("message").ThrowAndCatch();
            var json = ExceptionSerializer.Serialize(expected);

            var actual = ExceptionSerializer.Deserialize(json);

            actual.ShouldBeOfType<RequestException>();
            actual.Message.ShouldBe(expected.Message);
            actual.StackTrace.ShouldNotBeNullOrEmpty();
        }

        [Test]
        public void RequestException_Serialization_AddBreadcrumbs()
        {                        
            var json = ExceptionSerializer.Serialize(new RequestException("message").ThrowAndCatch());
            var actual = ExceptionSerializer.Deserialize(json);

            var breadcrumbs = ((RequestException)actual).Breadcrumbs;
            breadcrumbs.ShouldNotBeEmpty();
            breadcrumbs.First().ServiceName.ShouldBe("InfraTests");            
        }

        [Test]
        public void RequestException_SerializedTwice_AddAnotherBreadcrumb()
        {
            var json1 = ExceptionSerializer.Serialize(new RequestException("message").ThrowAndCatch());
            var actual1 = ExceptionSerializer.Deserialize(json1);
            var json2 = ExceptionSerializer.Serialize(actual1);
            var actual2 = ExceptionSerializer.Deserialize(json2); 

            var breadcrumbs = ((RequestException)actual2).Breadcrumbs;
            breadcrumbs.Count.ShouldBe(2);
            breadcrumbs[0].ServiceName.ShouldBe("InfraTests");
            breadcrumbs[1].ServiceName.ShouldBe("InfraTests");
        }

        [Test]
        public void CustomerFacingException_RoundTrip_IsIdentical()
        {
            var expected = new RequestException("message", 30000).ThrowAndCatch();
            var json = ExceptionSerializer.Serialize(expected);

            var actual = (RequestException)ExceptionSerializer.Deserialize(json);

            actual.ShouldBeOfType<RequestException>();
            actual.Message.ShouldBe(expected.Message);
            actual.ErrorCode.ShouldBe(expected.ErrorCode);
            actual.StackTrace.ShouldNotBeNullOrEmpty();
        }

        [Test]
        public void ExceptionTypeNotAvailable_RoundTrip_FallsBackToAvailableType()
        {
{'fraction_non_alphanumeric': 0.09957042037434796, 'fraction_numerical': 0.003835532371893219, 'mean_word_length': 2.672676056338028, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4827102', 'n_tokens_mistral': 1686, 'n_tokens_neox': 1653, 'n_words': 259}