<commit_before>require 'sinatra/base'
require 'rbconfig'
require 'open-uri'

module IntegrationHelper
  class Server
    extend Enumerable
    attr_accessor :server, :port, :pipe
    alias name server

    def self.all
      @all ||= []
    end

    def self.each(&block)
      all.each(&block)
    end

    def self.run(server, port)
      new(server, port).run
    end

    def app_file
      File.expand_path('../integration/app.rb', __FILE__)
    end

    def environment
      "development"
    end

    def initialize(server, port)
      @installed, @pipe, @server, @port = nil, nil, server, port
      Server.all << self
    end

    def run
      return unless installed?
      @log     = ""
      @pipe    = IO.popen(command)
      @started = Time.now
      warn "#{server} up and running on port #{port}" if ping
      at_exit { kill }
    end

    def expect(str)
      return if log.size < str.size or log[0, str.size] == str
      raise "Server did not start properly:\n\n#{log}"
    end

    def ping(timeout = 10)
      loop do
        return if alive?
        if Time.now - @started > timeout
          $stderr.puts command, log
          get('/ping')
        else
          expect "loading"
          sleep 0.1
        end
      end
    end

    def alive?
      3.times { get('/ping') }
      true
    rescue Errno::ECONNREFUSED => error
      false
    end

    def get(url)
      url = "http://127.0.0.1:#{port}#{url}"
      open(url).read
    end

    def log
      @log ||= ""
      loop { @log <<  @pipe.read_nonblock(1) }
    rescue Exception
      @log
    end

    def installed?
      return @installed unless @installed.nil?
      require server
      @installed = true
    rescue LoadError
      warn "#{server} is not installed, skipping integration tests"
      @installed = false
    end

    def command
      @command ||= begin
        cmd = ["RACK_ENV=#{environment}", "exec"]
        if RbConfig.respond_to? :ruby
          cmd << RbConfig.ruby.inspect
        else
          file, dir = RbConfig::CONFIG.values_at('ruby_install_name', 'bindir')
          cmd << File.expand_path(file, dir).inspect
        end
        cmd << "-I" << File.expand_path('../../lib', __FILE__).inspect
        cmd << app_file.inspect << '-s' << server << '-o' << '127.0.0.1' << '-p' << port
        cmd << "-e" << environment.to_s << '2>&1'
        cmd.join " "
      end
    end

    def kill
      return unless pipe
      Process.kill("KILL", pipe.pid)
    rescue NotImplementedError
      system "kill -9 #{pipe.pid}"
    end
  end

  def it(message, &block)
    Server.each do |server|
      next unless server.installed?
      super "with #{server.name}: #{message}" do
        self.server = server
        server.run unless server.alive?
        instance_eval(&block)
      end
    end
  end

  def self.extend_object(obj)
    super

    Sinatra::Base.server.each_with_index do |server, index|
      Server.run(server, 5000+index)
    end
  end
end<commit_msg>use PID for port (so two tests can run in parallel)<commit_after>require 'sinatra/base'
require 'rbconfig'
require 'open-uri'

module IntegrationHelper
  class Server
    extend Enumerable
    attr_accessor :server, :port, :pipe
    alias name server

    def self.all
      @all ||= []
    end

    def self.each(&block)
      all.each(&block)
    end

    def self.run(server, port)
      new(server, port).run
    end

    def app_file
      File.expand_path('../integration/app.rb', __FILE__)
    end

    def environment
      "development"
    end

    def initialize(server, port)
      @installed, @pipe, @server, @port = nil, nil, server, port
      Server.all << self
    end

    def run
      return unless installed?
      @log     = ""
      @pipe    = IO.popen(command)
      @started = Time.now
      warn "#{server} up and running on port #{port}" if ping
      at_exit { kill }
    end

    def expect(str)
      return if log.size < str.size or log[0, str.size] == str
      raise "Server did not start properly:\n\n#{log}"
    end

    def ping(timeout = 10)
      loop do
        return if alive?
        if Time.now - @started > timeout
          $stderr.puts command, log
          get('/ping')
        else
          expect "loading"
          sleep 0.1
        end
      end
    end

    def alive?
      3.times { get('/ping') }
      true
    rescue Errno::ECONNREFUSED => error
      false
    end

    def open(url)
      super("http://127.0.0.1:#{port}#{url}")
    end

    def get(url)
      open(url).read
    end

    def log
      @log ||= ""
      loop { @log <<  @pipe.read_nonblock(1) }
    rescue Exception
      @log
    end

    def installed?
      return @installed unless @installed.nil?
      require server
      @installed = true
    rescue LoadError
      warn "#{server} is not installed, skipping integration tests"
      @installed = false
    end

    def command
      @command ||= begin
        cmd = ["RACK_ENV=#{environment}", "exec"]
        if RbConfig.respond_to? :ruby
          cmd << RbConfig.ruby.inspect
        else
          file, dir = RbConfig::CONFIG.values_at('ruby_install_name', 'bindir')
          cmd << File.expand_path(file, dir).inspect
        end
        cmd << "-I" << File.expand_path('../../lib', __FILE__).inspect
        cmd << app_file.inspect << '-s' << server << '-o' << '127.0.0.1' << '-p' << port
        cmd << "-e" << environment.to_s << '2>&1'
        cmd.join " "
      end
    end

    def kill
      return unless pipe
      Process.kill("KILL", pipe.pid)
    rescue NotImplementedError
      system "kill -9 #{pipe.pid}"
    end
  end

  def it(message, &block)
    Server.each do |server|
      next unless server.installed?
      super "with #{server.name}: #{message}" do
        self.server = server
        server.run unless server.alive?
        instance_eval(&block)
      end
    end
  end

  def self.extend_object(obj)
    super

    base_port = 5000 + Process.pid % 100
    Sinatra::Base.server.each_with_index do |server, index|
      Server.run(server, 5000+index)
    end
  end
end
{'fraction_non_alphanumeric': 0.11971019265601844, 'fraction_numerical': 0.00971513255392722, 'mean_word_length': 1.9585971748660498, 'pattern_counts': {'":': 0, '<': 69, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, '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': '4763940', 'n_tokens_mistral': 1984, 'n_tokens_neox': 1893, 'n_words': 533}