Sha256: e4bd3beb793aff11faf18f57476a5066c7a14f7740b06e4f9f9c68df0503a10c

Contents?: true

Size: 1.86 KB

Versions: 17

Compression:

Stored size: 1.86 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)
      10.times do
        begin
          response = Excon.get(url)
          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)
      10.times do
        begin
          Excon.get("http://#{hostname}#{port.nil? ? '' : ':' + port.to_s}#{path || ''}")
          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

17 entries across 17 versions & 1 rubygems

Version Path
percy-common-3.1.5 lib/percy/network_helpers.rb
percy-common-3.1.4 lib/percy/network_helpers.rb
percy-common-3.1.3 lib/percy/network_helpers.rb
percy-common-3.1.2 lib/percy/network_helpers.rb
percy-common-3.1.2.pre.rc.3 lib/percy/network_helpers.rb
percy-common-3.1.2.pre.rc.2 lib/percy/network_helpers.rb
percy-common-3.1.2.rc.1 lib/percy/network_helpers.rb
percy-common-3.1.1 lib/percy/network_helpers.rb
percy-common-3.1.0 lib/percy/network_helpers.rb
percy-common-3.0.2 lib/percy/network_helpers.rb
percy-common-3.0.1 lib/percy/network_helpers.rb
percy-common-3.0.0 lib/percy/network_helpers.rb
percy-common-2.1.1 lib/percy/network_helpers.rb
percy-common-2.1.0 lib/percy/network_helpers.rb
percy-common-2.0.0 lib/percy/network_helpers.rb
percy-common-1.5.0 lib/percy/network_helpers.rb
percy-common-1.4.1 lib/percy/network_helpers.rb