<commit_before>﻿//-----------------------------------------------------------------------
// <copyright file="TcpIntegrationSpec.cs" company="Akka.NET Project">
//     Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
//     Copyright (C) 2013-2016 Akka.NET project <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Akka.Actor;
using Akka.IO;
using Akka.TestKit;
using Akka.Util.Internal;
using Xunit;
using Xunit.Abstractions;

namespace Akka.Tests.IO
{
    public class TcpIntegrationSpec : AkkaSpec
    {
        public TcpIntegrationSpec(ITestOutputHelper output)
            : base(@"akka.loglevel = DEBUG
                     akka.io.tcp.trace-logging = true", output: output)
        { }

        private void VerifyActorTermination(IActorRef actor)
        {
            Watch(actor);
            ExpectTerminated(actor);
        }

        [Fact]
        public void The_TCP_transport_implementation_should_properly_bind_a_test_server()
        {
            new TestSetup(this).Run(x => { });
        }

        [Fact(Skip="FIXME .net core / linux")]
        public void The_TCP_transport_implementation_should_allow_connecting_to_and_disconnecting_from_the_test_server()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                actors.ClientHandler.Send(actors.ClientConnection, Tcp.Close.Instance);
                actors.ClientHandler.ExpectMsg<Tcp.Closed>();
                
                actors.ServerHandler.ExpectMsg<Tcp.PeerClosed>();
                VerifyActorTermination(actors.ClientConnection);
                VerifyActorTermination(actors.ServerConnection);
            });
        }

        [Fact(Skip="FIXME .net core / linux")]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_from_client_side()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                actors.ClientHandler.Send(actors.ClientConnection, Tcp.Abort.Instance);
                actors.ClientHandler.ExpectMsg<Tcp.Aborted>();
                actors.ServerHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ClientConnection);
                VerifyActorTermination(actors.ServerConnection);
            });
        }

        [Fact(Skip="FIXME .net core / linux")]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_from_client_side_after_chit_chat()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                ChitChat(actors);

                actors.ClientHandler.Send(actors.ClientConnection, Tcp.Abort.Instance);
                actors.ClientHandler.ExpectMsg<Tcp.Aborted>();
                actors.ServerHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ClientConnection);
                VerifyActorTermination(actors.ServerConnection);
            });   
        }

        [Fact]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_via_PoisonPill_from_client_side()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                actors.ClientHandler.Send(actors.ClientConnection, PoisonPill.Instance);
                VerifyActorTermination(actors.ClientConnection);

                actors.ServerHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ServerConnection);
            });
        }

        [Fact]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_via_PoisonPill_from_client_side_after_chit_chat()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                ChitChat(actors);

                actors.ClientHandler.Send(actors.ClientConnection, PoisonPill.Instance);
                VerifyActorTermination(actors.ClientConnection);

                actors.ServerHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ServerConnection);
            });
        }

        [Fact]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_via_PoisonPill_from_server_side()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                actors.ServerHandler.Send(actors.ServerConnection, PoisonPill.Instance);
                VerifyActorTermination(actors.ServerConnection);

                actors.ClientHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ClientConnection);
            });
        }

        [Fact]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_via_PoisonPill_from_server_side_after_chit_chat()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                ChitChat(actors);

                actors.ServerHandler.Send(actors.ServerConnection, PoisonPill.Instance);
                VerifyActorTermination(actors.ServerConnection);

                actors.ClientHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ClientConnection);
            });
        }

        class Aye : Tcp.Event { public static readonly Aye Instance = new Aye();}
        class Yes : Tcp.Event { public static readonly Yes Instance = new Yes();}
        [Fact]
        public void The_TCP_transport_implementation_should_properly_complete_one_client_server_request_response_cycle()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();

                actors.ClientHandler.Send(actors.ClientConnection, Tcp.Write.Create(ByteString.FromString("Captain on the bridge!"), Aye.Instance));
                actors.ClientHandler.ExpectMsg(Aye.Instance);
                actors.ServerHandler.ExpectMsg<Tcp.Received>().Data.ToString(Encoding.ASCII).ShouldBe("Captain on the bridge!");

                actors.ServerHandler.Send(actors.ServerConnection, Tcp.Write.Create(ByteString.FromString("For the king!"), Yes.Instance));
                actors.ServerHandler.ExpectMsg(Yes.Instance);
                actors.ClientHandler.ExpectMsg<Tcp.Received>().Data.ToString(Encoding.ASCII).ShouldBe("For the king!");

                actors.ServerHandler.Send(actors.ServerConnection, Tcp.Close.Instance);
                actors.ServerHandler.ExpectMsg<Tcp.Closed>();
                actors.ClientHandler.ExpectMsg<Tcp.PeerClosed>();

                VerifyActorTermination(actors.ClientConnection);
                VerifyActorTermination(actors.ServerConnection);
            });<commit_msg>added reproduction failure for #3021<commit_after>﻿//-----------------------------------------------------------------------
// <copyright file="TcpIntegrationSpec.cs" company="Akka.NET Project">
//     Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
//     Copyright (C) 2013-2016 Akka.NET project <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Akka.Actor;
using Akka.IO;
using Akka.TestKit;
using Akka.Util.Internal;
using Xunit;
using Xunit.Abstractions;

namespace Akka.Tests.IO
{
    public class TcpIntegrationSpec : AkkaSpec
    {
        public TcpIntegrationSpec(ITestOutputHelper output)
            : base(@"akka.loglevel = DEBUG
                     akka.io.tcp.trace-logging = true", output: output)
        { }

        private void VerifyActorTermination(IActorRef actor)
        {
            Watch(actor);
            ExpectTerminated(actor);
        }

        [Fact]
        public void The_TCP_transport_implementation_should_properly_bind_a_test_server()
        {
            new TestSetup(this).Run(x => { });
        }

        [Fact(Skip="FIXME .net core / linux")]
        public void The_TCP_transport_implementation_should_allow_connecting_to_and_disconnecting_from_the_test_server()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                actors.ClientHandler.Send(actors.ClientConnection, Tcp.Close.Instance);
                actors.ClientHandler.ExpectMsg<Tcp.Closed>();
                
                actors.ServerHandler.ExpectMsg<Tcp.PeerClosed>();
                VerifyActorTermination(actors.ClientConnection);
                VerifyActorTermination(actors.ServerConnection);
            });
        }

        [Fact(Skip="FIXME .net core / linux")]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_from_client_side()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                actors.ClientHandler.Send(actors.ClientConnection, Tcp.Abort.Instance);
                actors.ClientHandler.ExpectMsg<Tcp.Aborted>();
                actors.ServerHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ClientConnection);
                VerifyActorTermination(actors.ServerConnection);
            });
        }

        [Fact(Skip="FIXME .net core / linux")]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_from_client_side_after_chit_chat()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                ChitChat(actors);

                actors.ClientHandler.Send(actors.ClientConnection, Tcp.Abort.Instance);
                actors.ClientHandler.ExpectMsg<Tcp.Aborted>();
                actors.ServerHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ClientConnection);
                VerifyActorTermination(actors.ServerConnection);
            });   
        }

        [Fact]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_via_PoisonPill_from_client_side()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                actors.ClientHandler.Send(actors.ClientConnection, PoisonPill.Instance);
                VerifyActorTermination(actors.ClientConnection);

                actors.ServerHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ServerConnection);
            });
        }

        [Fact]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_via_PoisonPill_from_client_side_after_chit_chat()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                ChitChat(actors);

                actors.ClientHandler.Send(actors.ClientConnection, PoisonPill.Instance);
                VerifyActorTermination(actors.ClientConnection);

                actors.ServerHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ServerConnection);
            });
        }

        [Fact]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_via_PoisonPill_from_server_side()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                actors.ServerHandler.Send(actors.ServerConnection, PoisonPill.Instance);
                VerifyActorTermination(actors.ServerConnection);

                actors.ClientHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ClientConnection);
            });
        }

        [Fact]
        public void The_TCP_transport_implementation_should_properly_handle_connection_abort_via_PoisonPill_from_server_side_after_chit_chat()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();
                ChitChat(actors);

                actors.ServerHandler.Send(actors.ServerConnection, PoisonPill.Instance);
                VerifyActorTermination(actors.ServerConnection);

                actors.ClientHandler.ExpectMsg<Tcp.ErrorClosed>();
                VerifyActorTermination(actors.ClientConnection);
            });
        }

        [Fact]
        public void BugFix_3021_Tcp_Should_not_drop_large_messages()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();

                // create a 256 byte string
                var str = Enumerable.Repeat("f", 128).Join("");
                var testData = ByteString.FromString(str);

                // queue 3 writes
                actors.ClientHandler.Send(actors.ClientConnection, Tcp.Write.Create(testData));
                actors.ClientHandler.Send(actors.ClientConnection, Tcp.Write.Create(testData));
                actors.ClientHandler.Send(actors.ClientConnection, Tcp.Write.Create(testData));

                var serverMsgs = actors.ServerHandler.ReceiveN(3, TimeSpan.FromMinutes(10));
                
            });
        }

        class Aye : Tcp.Event { public static readonly Aye Instance = new Aye();}
        class Yes : Tcp.Event { public static readonly Yes Instance = new Yes();}
        [Fact]
        public void The_TCP_transport_implementation_should_properly_complete_one_client_server_request_response_cycle()
        {
            new TestSetup(this).Run(x =>
            {
                var actors = x.EstablishNewClientConnection();

                actors.ClientHandler.Send(actors.ClientConnection, Tcp.Write.Create(ByteString.FromString("Captain on the bridge!"), Aye.Instance));
                actors.ClientHandler.ExpectMsg(Aye.Instance);
                actors.ServerHandler.ExpectMsg<Tcp.Received>().Data.ToString(Encoding.ASCII).ShouldBe("Captain on the bridge!");

                actors.ServerHandler.Send(actors.ServerConnection, Tcp.Write.Create(ByteString.FromString("For the king!"), Yes.Instance));
                actors.ServerHandler.ExpectMsg(Yes.Instance);
                actors.ClientHandler.ExpectMsg<Tcp.Received>().Data.ToString(Encoding.ASCII).ShouldBe("For the king!");

                actors.ServerHandler.Send(actors.ServerConnection, Tcp.Close.Instance);
                actors.ServerHandler.ExpectMsg<Tcp.Closed>();
                actors.ClientHandler.ExpectMsg<Tcp.PeerClosed>();

                VerifyActorTermination(actors.ClientConnection);
                VerifyActorTermination(actors.ServerConnection);
            });
{'fraction_non_alphanumeric': 0.11014511700875931, 'fraction_numerical': 0.003268401098182769, 'mean_word_length': 2.1806652806652806, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 58, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, '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': '3424289', 'n_tokens_mistral': 4128, 'n_tokens_neox': 3853, 'n_words': 512}