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.4
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
- [ :selenium_server_address, :selenium_server_port,
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
- @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")
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
- return
18
- # just return; tunnel is all in transient memory, and we don't want to hang or abort the whole test suite anyway
19
- # This could potentially be a problem when opening an SshTunnel multiple times during a single interpreter, but we'll see...
20
- # if @gateway
21
- # say "Shutting down ssh reverse tunnel"
22
- # @gateway.close(@port) if @port
23
- # @gateway.shutdown! if @gateway
24
- # end
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
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 8
8
- - 4
9
- version: 0.8.4
8
+ - 5
9
+ version: 0.8.5
10
10
  platform: ruby
11
11
  authors:
12
12
  - Kelly Felkins, Chad Woolley & Sam Pierson