<commit_before>require 'spec_helper'
require 'support/async_helper'
require 'socket'

module ActivityBroker
  describe EventLoop do
    include AsyncHelper

    class FakeIO
      def initialize(io)
        @io = io
      end

      def to_io
        @io
      end

      def read_ready_connection
        @read_ready_connection = true
      end

      def close
        @io.close
      end

      def reset
        @read_ready_connection = false
        @write_ready_connection = false
      end

      def has_received_read_ready_connection?
        @read_ready_connection
      end

      def write_ready_connection
        @write_ready_connection = true
      end

      def has_received_write_ready_connection?
        @write_ready_connection
      end
    end

    subject { EventLoop.new(double.as_null_object) }

    def server
      @server
    end

    def socket
      @socket
    end

    after(:all) do
      server.close
      socket.close
    end

    after(:each) do
      subject.stop
      @thread.kill
    end

    before(:all) do
      @server = TCPServer.new('localhost', 9595)
      @socket = TCPSocket.new('localhost', 9595)
    end

    def start_event_loop
      @thread = Thread.new { subject.start }
      @thread.abort_on_exception = true
    end

    it 'notifies when a read operation is ready' do
      fake_server = FakeIO.new(server)

      subject.register_read(fake_server, :read_ready_connection)

      start_event_loop

      eventually { expect(fake_server).to have_received_read_ready_connection }

      subject.deregister_read(fake_server, :read_ready_connection)
    end

    it 'notifies when a write operation is ready' do
      fake_socket = FakeIO.new(socket)

      subject.register_write(fake_socket, :write_ready_connection)

      start_event_loop

      eventually { expect(fake_socket).to have_received_write_ready_connection }

      subject.deregister_write(fake_socket, :write_ready_connection)
    end

    it 'allows to deregister from a read operation' do
      fake_server = FakeIO.new(server)

      subject.register_read(fake_server, :read_ready_connection)

      start_event_loop

      eventually do
        expect(fake_server).to have_received_read_ready_connection
      end

      fake_server.reset

      connection = server.accept_nonblock # accept outstanding connection

      subject.deregister_read(fake_server, :read_ready_connection)

      another_socket = TCPSocket.new('localhost', 9595)

      during(timeout: 0.1) do
        expect(fake_server).to_not have_received_read_ready_connection
      end
    end

    it 'allows to deregister from a write operation' do
      fake_socket = FakeIO.new(socket)

      subject.register_write(fake_socket, :write_ready_connection)

      start_event_loop

      eventually { expect(fake_socket).to have_received_write_ready_connection }

      fake_socket.reset

      subject.deregister_write(fake_socket, :write_ready_connection)

      during(timeout: 0.1) do
        expect(fake_socket).not_to have_received_write_ready_connection
      end
    end
  end<commit_msg>Use rspec spies instead of rolling our own<commit_after>require 'spec_helper'
require 'support/async_helper'
require 'socket'

module ActivityBroker
  describe EventLoop do
    include AsyncHelper

    let!(:event_loop) { EventLoop.new(double.as_null_object) }

    def server
      @server
    end

    def socket
      @socket
    end

    after(:all) do
      server.close
      socket.close
    end

    after(:each) do
      event_loop.stop
      @thread.kill
    end

    before(:all) do
      @server = TCPServer.new('localhost', 9595)
      @socket = TCPSocket.new('localhost', 9595)
    end

    def start_event_loop
      @thread = Thread.new { event_loop.start }
      @thread.abort_on_exception = true
    end

    it 'notifies when a read operation is ready' do
      fake_server = double(to_io: server, connection_read_ready: nil)

      event_loop.register_read(fake_server, :connection_read_ready)

      start_event_loop

      eventually do
        expect(fake_server).to have_received(:connection_read_ready).at_least(:once)
      end

      event_loop.deregister_read(fake_server, :connection_read_ready)
    end

    it 'notifies when a write operation is ready' do
      fake_socket = double(to_io: socket, connection_write_ready: nil)

      event_loop.register_write(fake_socket, :connection_write_ready)

      start_event_loop

      eventually do
        expect(fake_socket).to have_received(:connection_write_ready).at_least(:once)
      end

      event_loop.deregister_write(fake_socket, :connection_write_ready)
    end

    it 'allows to deregister from a read operation' do
      fake_server = double(to_io: server, connection_read_ready: nil)

      event_loop.register_read(fake_server, :connection_read_ready)

      event_loop.deregister_read(fake_server, :connection_read_ready)

      start_event_loop

      during(timeout: 0.1) do
        expect(fake_server).to_not have_received(:connection_read_ready)
      end
    end

    it 'allows to deregister from a write operation' do
      fake_socket = double(to_io: socket, connection_write_ready: nil)

      event_loop.register_write(fake_socket, :connection_write_ready)

      event_loop.deregister_write(fake_socket, :connection_write_ready)

      start_event_loop

      during(timeout: 0.1) do
        expect(fake_socket).to_not have_received(:connection_write_ready)
      end
    end
  end
{'fraction_non_alphanumeric': 0.06518166879678657, 'fraction_numerical': 0.005112287748767573, 'mean_word_length': 2.963820549927641, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '5974749', 'n_tokens_mistral': 1713, 'n_tokens_neox': 1607, 'n_words': 355}