Sha256: 1b301b6d2b90b50ee3c51b59e30760dc8c4273a38b7d88c72e71c1a6a226a681

Contents?: true

Size: 1.94 KB

Versions: 1

Compression:

Stored size: 1.94 KB

Contents

require 'socket'
require 'excon'

module Percy
  class NetworkHelpers
    MIN_PORT = 1_024 # 0-1023 are not available without privilege
    MAX_PORT = 65_535 # (2^16) -1
    MAX_PORT_ATTEMPTS = 50

    class ServerDown < RuntimeError; end
    class OpenPortNotFound < RuntimeError; end

    def self.random_open_port
      MAX_PORT_ATTEMPTS.times do
        port = rand(MIN_PORT..MAX_PORT)
        return port if port_open? port
      end

      raise OpenPortNotFound
    end

    def self.port_open?(port)
      begin
        TCPServer.new(port).close
        true
      rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::EADDRINUSE
        false
      end
    end

    def self.verify_healthcheck(url:, expected_body: 'ok', retry_wait_seconds: 0.5, proxy: nil)
      10.times do
        begin
          response = Excon.get(url, proxy: proxy)
          return true if response.body == expected_body
        rescue Excon::Error::Socket, Excon::Error::Timeout
          sleep retry_wait_seconds
        end
      end
      raise ServerDown, "Healthcheck failed for #{url}"
    end

    def self.verify_http_server_up(hostname, port: nil,
      path: nil, retry_wait_seconds: 0.25, proxy: nil)
      10.times do
        begin
          url = "http://#{hostname}#{port.nil? ? '' : ':' + port.to_s}#{path || ''}"
          Excon.get(url, proxy: proxy)
          return true
        rescue Excon::Error::Socket, Excon::Error::Timeout
          sleep retry_wait_seconds
        end
      end
      raise ServerDown, "Server is down: #{hostname}"
    end

    def self.serve_static_directory(dir, hostname: 'localhost', port: nil)
      port ||= random_open_port

      # Note: using this form of popen to keep stdout and stderr silent and captured.
      process = IO.popen(
        [
          'ruby', '-run', '-e', 'httpd', dir, '-p', port.to_s, err: [:child, :out],
        ].flatten,
      )
      verify_http_server_up(hostname, port: port)
      process.pid
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
percy-common-3.1.6 lib/percy/network_helpers.rb