saucelabs-adapter 0.8.4 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
    
        data/README.markdown
    CHANGED
    
    | @@ -123,6 +123,12 @@ Resources | |
| 123 123 |  | 
| 124 124 | 
             
            NOTABLE CHANGES
         | 
| 125 125 | 
             
            ===============
         | 
| 126 | 
            +
             | 
| 127 | 
            +
            0.8.5
         | 
| 128 | 
            +
            -----
         | 
| 129 | 
            +
            - Allow application_port to be a range of form: XXXX-YYYY, e.g. 4000-5000.  The SaucelabsAdapter will find an unused port in that range.
         | 
| 130 | 
            +
            - Allow specification of the test framework in use.  If test_framework == :webrat and tunnel_mode == :sshtunnel, the generated unused port will also be written to tunnel_to_localhost_port
         | 
| 131 | 
            +
             | 
| 126 132 | 
             
            0.8
         | 
| 127 133 | 
             
            ---
         | 
| 128 134 | 
             
            - Added new tunnel type SshTunnel (a generic reverse SSH tunnel), see selenium.yml for now to configure.
         | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.8. | 
| 1 | 
            +
            0.8.5
         | 
| @@ -21,6 +21,7 @@ local_jsunit: | |
| 21 21 | 
             
            #                       "googlechrome"      ""
         | 
| 22 22 | 
             
            # "Linux"               "firefox"           "3."
         | 
| 23 23 | 
             
            saucelabs: &saucelabs
         | 
| 24 | 
            +
              test_framework: webrat
         | 
| 24 25 | 
             
              # URL of Selenium RC server:
         | 
| 25 26 | 
             
              selenium_server_address: "saucelabs.com"
         | 
| 26 27 | 
             
              selenium_server_port: "4444"
         | 
| @@ -43,7 +44,7 @@ saucelabs: &saucelabs | |
| 43 44 | 
             
              #
         | 
| 44 45 | 
             
              # tunnel_method: :sshtunnel
         | 
| 45 46 | 
             
              # application_address: proxy.mycompany.com
         | 
| 46 | 
            -
              # application_port: 12345
         | 
| 47 | 
            +
              # application_port: 12345 # or can be a range XXXX-YYYY
         | 
| 47 48 | 
             
              # tunnel_to_localhost_port: 4000 # Warning: application_port and tunnel_to_localhost_port must be identical if you are using Webrat
         | 
| 48 49 | 
             
              # tunnel_username: fred
         | 
| 49 50 | 
             
              # tunnel_keyfile: "/path/to/keyfile"  # or tunnel_password: "password"
         | 
| @@ -15,7 +15,8 @@ module SaucelabsAdapter | |
| 15 15 | 
             
                  @configuration[attribute.to_s] = value
         | 
| 16 16 | 
             
                end
         | 
| 17 17 |  | 
| 18 | 
            -
                [ : | 
| 18 | 
            +
                [ :test_framework,
         | 
| 19 | 
            +
                  :selenium_server_address, :selenium_server_port,
         | 
| 19 20 | 
             
                  :application_address, :application_port,
         | 
| 20 21 | 
             
                  :saucelabs_username, :saucelabs_access_key,
         | 
| 21 22 | 
             
                  :saucelabs_browser_os, :saucelabs_browser, :saucelabs_browser_version,
         | 
| @@ -106,6 +107,11 @@ module SaucelabsAdapter | |
| 106 107 | 
             
                def build_configuration(configuration_name)
         | 
| 107 108 | 
             
                  @configuration = @@selenium_configs[configuration_name]
         | 
| 108 109 | 
             
                  raise "[saucelabs-adapter] stanza '#{configuration_name}' not found in #{@selenium_yml}" unless @configuration
         | 
| 110 | 
            +
                  # If the Saucelabs-Adapter picked a port out of a range during this session, use it.
         | 
| 111 | 
            +
                  if ENV['SAUCELABS_ADAPTER_APPLICATION_PORT']
         | 
| 112 | 
            +
                    @configuration['application_port'] = ENV['SAUCELABS_ADAPTER_APPLICATION_PORT'].to_i
         | 
| 113 | 
            +
                    debug("Using application port #{application_port} from environment variable SAUCELABS_ADAPTER_APPLICATION_PORT", 2)
         | 
| 114 | 
            +
                  end
         | 
| 109 115 | 
             
                  check_configuration(configuration_name)
         | 
| 110 116 | 
             
                end
         | 
| 111 117 |  | 
| @@ -129,6 +135,14 @@ module SaucelabsAdapter | |
| 129 135 | 
             
                          errors << require_attributes([:tunnel_password, :tunnel_keyfile],
         | 
| 130 136 | 
             
                                                       :when => "when tunnel_method is :sshtunnel",
         | 
| 131 137 | 
             
                                                       :any_or_all => :any)
         | 
| 138 | 
            +
                          if application_address && application_port.is_a?(String) && application_port =~ /(\d+)-(\d+)/
         | 
| 139 | 
            +
                            # We have been given a port range. Find an unused one.
         | 
| 140 | 
            +
                            port = find_unused_port(application_address, ($1.to_i)..($2.to_i))
         | 
| 141 | 
            +
                            @configuration['application_port'] = port
         | 
| 142 | 
            +
                            @configuration['tunnel_to_localhost_port'] = port if test_framework == :webrat
         | 
| 143 | 
            +
                            # Pass this calculated value on to any other instances of SeleniumConfig created
         | 
| 144 | 
            +
                            ENV['SAUCELABS_ADAPTER_APPLICATION_PORT'] = port.to_s
         | 
| 145 | 
            +
                          end
         | 
| 132 146 | 
             
                          if tunnel_keyfile && !File.exist?(File.expand_path(tunnel_keyfile))
         | 
| 133 147 | 
             
                            errors << "tunnel_keyfile '#{tunnel_keyfile}' does not exist" 
         | 
| 134 148 | 
             
                          end
         | 
| @@ -10,18 +10,25 @@ module SaucelabsAdapter | |
| 10 10 | 
             
                  say "Setting up SSH reverse tunnel from #{@se_config.application_address}:#{@se_config.application_port} to localhost:#{@se_config.tunnel_to_localhost_port}"
         | 
| 11 11 | 
             
                  options = @se_config.tunnel_password ? { :password => @se_config.tunnel_password } : { :keys => @se_config.tunnel_keyfile }
         | 
| 12 12 | 
             
                  @gateway = Net::SSH::Gateway.new(@se_config.application_address, @se_config.tunnel_username, options)
         | 
| 13 | 
            -
                  @ | 
| 13 | 
            +
                  @host_and_port = @gateway.open_remote(@se_config.tunnel_to_localhost_port.to_i, "127.0.0.1", @se_config.application_port.to_i, "0.0.0.0")
         | 
| 14 14 | 
             
                end
         | 
| 15 15 |  | 
| 16 16 | 
             
                def shutdown
         | 
| 17 | 
            -
                   | 
| 18 | 
            -
                  #  | 
| 19 | 
            -
                  #  | 
| 20 | 
            -
                  #  | 
| 21 | 
            -
                   | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 17 | 
            +
                  # We have experienced problems with the tunnel shutdown hanging.
         | 
| 18 | 
            +
                  # Previously the method was a no-op and we just exited the process which had the effect of closing the tunnel.
         | 
| 19 | 
            +
                  # However we are now running multiple tunnels in one process (sequentially), so we need to actually do a shutdown.
         | 
| 20 | 
            +
                  # So let's add a timeout.
         | 
| 21 | 
            +
                  if @gateway
         | 
| 22 | 
            +
                    begin
         | 
| 23 | 
            +
                      Timeout::timeout(15) do
         | 
| 24 | 
            +
                        say "Shutting down ssh reverse tunnel"
         | 
| 25 | 
            +
                        @gateway.close_remote(*@host_and_port) if @host_and_port
         | 
| 26 | 
            +
                        @gateway.shutdown! if @gateway
         | 
| 27 | 
            +
                      end
         | 
| 28 | 
            +
                    rescue Timeout::Error
         | 
| 29 | 
            +
                      say "tunnel shutdown timed out"
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                  end
         | 
| 25 32 | 
             
                end
         | 
| 26 33 | 
             
              end
         | 
| 27 34 | 
             
            end
         | 
| @@ -19,5 +19,20 @@ module SaucelabsAdapter | |
| 19 19 | 
             
                def raise_with_message(message)
         | 
| 20 20 | 
             
                  raise "#{diagnostics_prefix} #{message}"
         | 
| 21 21 | 
             
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def find_unused_port(hostname, range = (3000..5000))
         | 
| 24 | 
            +
                  debug 'searching for unused port', 2
         | 
| 25 | 
            +
                  range.each do |port|
         | 
| 26 | 
            +
                    debug "trying #{hostname}:#{port}", 2
         | 
| 27 | 
            +
                    begin
         | 
| 28 | 
            +
                      socket = TCPSocket.new(hostname, port)
         | 
| 29 | 
            +
                    rescue Errno::ECONNREFUSED
         | 
| 30 | 
            +
                      debug "it's good, returning #{port}", 2
         | 
| 31 | 
            +
                      return port
         | 
| 32 | 
            +
                    ensure
         | 
| 33 | 
            +
                      socket.close if socket
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 22 37 | 
             
              end
         | 
| 23 38 | 
             
            end
         |