Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check if we already have the latest/desired version before checking for updates. #49

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions lib/webdrivers/chromedriver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ def current_version
end

def latest_version
raise StandardError, 'Can not reach site' unless site_available?
unless site_available?
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a thought, if we could add a configuration option to disable all network calls, then we could make an early return current_version before this line, if the option is set.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm planning on doing that very soon.

cur_ver = current_version
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not as big of a deal since they aren't network calls, but some paths through this code are also calling #current_version multiple times in a single update. Let's memoize it and then set it back to nil in the #remove method.

raise StandardError, update_failed_msg if cur_ver.nil? # Site is down and no existing binary

Webdrivers.logger.warn "Can not reach update site. Using existing #{file_name} #{cur_ver}"
return cur_ver
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might not be the right logic here... We might want to throw an error instead of a warning if the driver & browser versions are technically incompatible.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, makes sense. I'm going to go ahead and refactor more code than I'd originally anticipated. Will make a list of all cases and then check them off one by one.

end

# Versions before 70 do not have a LATEST_RELEASE file
return Gem::Version.new('2.46') if release_version < '70.0.3538'
Expand Down Expand Up @@ -89,7 +95,7 @@ def chrome_on_windows

# Workaround for Google Chrome when using Jruby on Windows.
# @see https://github.com/titusfortner/webdrivers/issues/41
if RUBY_PLATFORM == 'java' && platform == 'win'
if RUBY_PLATFORM == 'java'
ver = 'powershell (Get-Item -Path ((Get-ItemProperty "HKLM:\\Software\\Microsoft' \
"\\Windows\\CurrentVersion\\App` Paths\\chrome.exe\").\\'(default)\\'))" \
'.VersionInfo.ProductVersion'
Expand Down
76 changes: 56 additions & 20 deletions lib/webdrivers/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,52 @@ class << self
attr_accessor :version

def update
if correct_binary? # Already have desired or latest version
Webdrivers.logger.debug 'Expected webdriver version found'
return binary
end

# If site is down
unless site_available?
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've already checked for site availability, no need to make another call to get the same info. Let's memoize this method.

return current_version.nil? ? nil : binary
# No existing binary and we can't download
raise StandardError, update_failed_msg if current_version.nil?

# Use existing binary
Webdrivers.logger.error "Can not reach update site. Using existing #{file_name} #{current_version}"
return binary
end

# Newer not specified or latest not found, so use existing
return binary if desired_version.nil? && File.exist?(binary)

# Can't find desired and no existing binary
if desired_version.nil?
msg = "Unable to find the latest version of #{file_name}; try downloading manually from #{base_url} and place in #{install_dir}"
raise StandardError, msg
end

if correct_binary?
Webdrivers.logger.debug 'Expected webdriver version found'
return binary
end
raise StandardError, update_failed_msg if desired_version.nil?

remove # Remove outdated exe
download # Fetch latest
download # Fetch desired or latest
end

def desired_version
if version.is_a?(Gem::Version)
version
elsif version.nil?
latest_version
else
Gem::Version.new(version.to_s)
end
ver = if version.is_a?(Gem::Version)
version
elsif version.nil?
latest_version
else
Gem::Version.new(version.to_s)
end

Webdrivers.logger.debug "Desired version: #{ver}"
ver
end

def latest_version
raise StandardError, 'Can not reach site' unless site_available?
unless site_available?
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's swap this around; put this at the beginning:

return downloads.keys.max if site_available?

That'll let you remove the the unless block.

cur_ver = current_version
raise StandardError, update_failed_msg if cur_ver.nil? # Site is down and no existing binary

Webdrivers.logger.error "Can not reach update site. Using existing #{file_name} #{cur_ver}"
return cur_ver
end

downloads.keys.max
end
Expand All @@ -51,9 +63,10 @@ def remove
end

def download
raise StandardError, 'Can not reach site' unless site_available?
raise StandardError, update_failed_msg unless site_available?

url = downloads[desired_version]
Webdrivers.logger.debug "Downloading #{url}"
filename = File.basename url

FileUtils.mkdir_p(install_dir) unless File.exist?(install_dir)
Expand Down Expand Up @@ -91,13 +104,31 @@ def binary
File.join install_dir, file_name
end

#
# Returns count of network request made to the base url. Used for debugging
# purpose only.
#
def network_requests
@network_requests || 0
end

#
# Resets network request count to 0.
#
def reset_network_requests
@network_requests = 0
end

protected

def get(url, limit = 10)
raise StandardError, 'Too many HTTP redirects' if limit.zero?

@network_requests ||= 0
response = http.get_response(URI(url))
Webdrivers.logger.debug "Get response: #{response.inspect}"
@network_requests += 1
Webdrivers.logger.debug "Successful network request ##{@network_requests}"

case response
when Net::HTTPSuccess
Expand Down Expand Up @@ -200,6 +231,11 @@ def correct_binary?
def normalize(string)
Gem::Version.new(string)
end

def update_failed_msg
"Update site is unreachable. Try downloading '#{file_name}' manually from " \
"#{base_url} and place in '#{install_dir}'"
end
end
end
end
31 changes: 27 additions & 4 deletions spec/webdrivers/chromedriver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

describe Webdrivers::Chromedriver do
let(:chromedriver) { described_class }
let(:update_failed_msg) { /^Update site is unreachable. Try downloading 'chromedriver(.exe)?' manually from (.*)?and place in '(.*)?\.webdrivers'$/ }

it 'updates' do
chromedriver.update
Expand Down Expand Up @@ -42,6 +43,25 @@
expect(chromedriver.current_version.version).to eq '73.0.3683.68'
end

it 'does not download if desired version already exists' do
chromedriver.remove
chromedriver.version = '73.0.3683.68'
chromedriver.update
chromedriver.reset_network_requests
chromedriver.update
expect(chromedriver.network_requests).to be(0)
end

it 'uses existing version if update site is unreachable' do
chromedriver.remove
chromedriver.version = '2.46'
chromedriver.download
allow(chromedriver).to receive(:site_available?).and_return(false)
chromedriver.version = nil
chromedriver.update
expect(chromedriver.latest_version.version).to include('2.46')
end

it 'removes chromedriver' do
chromedriver.remove
expect(chromedriver.current_version).to be_nil
Expand Down Expand Up @@ -76,14 +96,17 @@
end

context 'when offline' do
before { allow(chromedriver).to receive(:site_available?).and_return(false) }
before do
chromedriver.remove
allow(chromedriver).to receive(:site_available?).and_return(false)
end

it 'raises exception finding latest version' do
expect { chromedriver.latest_version }.to raise_error(StandardError, 'Can not reach site')
it 'raises exception finding latest version if no existing binary' do
expect { chromedriver.latest_version }.to raise_error(StandardError, update_failed_msg)
end

it 'raises exception downloading' do
expect { chromedriver.download }.to raise_error(StandardError, 'Can not reach site')
expect { chromedriver.download }.to raise_error(StandardError, update_failed_msg)
end
end

Expand Down
35 changes: 29 additions & 6 deletions spec/webdrivers/geckodriver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

describe Webdrivers::Geckodriver do
let(:geckodriver) { described_class }
let(:update_failed_msg) { /^Update site is unreachable. Try downloading 'geckodriver(.exe)?' manually from (.*)?and place in '(.*)?\.webdrivers'$/ }

it 'raises exception if unable to get latest geckodriver and no geckodriver present' do
geckodriver.remove
allow(geckodriver).to receive(:desired_version).and_return(nil)
msg = /^Unable to find the latest version of geckodriver(.exe)?; try downloading manually from (.*)?and place in (.*)?\.webdrivers$/
expect { geckodriver.update }.to raise_exception StandardError, msg
expect { geckodriver.update }.to raise_exception StandardError, update_failed_msg
end

it 'uses found version of geckodriver if latest release unable to be found' do
Expand All @@ -30,6 +30,15 @@
expect(geckodriver.current_version).to eq geckodriver.desired_version
end

it 'does not download if desired version already exists' do
geckodriver.remove
geckodriver.version = '0.23.0'
geckodriver.download
geckodriver.reset_network_requests
geckodriver.update
expect(geckodriver.network_requests).to be(0)
end

it 'downloads specified version' do
begin
geckodriver.remove
Expand All @@ -41,20 +50,34 @@
end
end

it 'uses existing version if update site is unreachable' do
geckodriver.remove
geckodriver.version = '0.23.0'
geckodriver.download
allow(geckodriver).to receive(:site_available?).and_return(false)
geckodriver.update
geckodriver.version = nil
expect(geckodriver.latest_version.version).to eq '0.23.0'
end

it 'removes geckodriver' do
geckodriver.remove
expect(geckodriver.current_version).to be_nil
end

context 'when offline' do
before { allow(geckodriver).to receive(:site_available?).and_return(false) }
before do
allow(geckodriver).to receive(:site_available?).and_return(false)
geckodriver.remove
geckodriver.version = nil
end

it 'raises exception finding latest version' do
expect { geckodriver.desired_version }.to raise_error(StandardError, 'Can not reach site')
it 'raises exception finding latest version if no existing binary' do
expect { geckodriver.desired_version }.to raise_error(StandardError, update_failed_msg)
end

it 'raises exception downloading' do
expect { geckodriver.download }.to raise_error(StandardError, 'Can not reach site')
expect { geckodriver.download }.to raise_error(StandardError, update_failed_msg)
end
end
end
10 changes: 7 additions & 3 deletions spec/webdrivers/i_edriver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

describe Webdrivers::IEdriver do
let(:iedriver) { described_class }
let(:update_failed_msg) { /^Update site is unreachable. Try downloading 'IEDriverServer(.exe)?' manually from (.*)?and place in '(.*)?\.webdrivers'$/ }

it 'finds latest version' do
old_version = Gem::Version.new('3.12.0')
Expand All @@ -23,14 +24,17 @@
end

context 'when offline' do
before { allow(iedriver).to receive(:site_available?).and_return(false) }
before do
allow(iedriver).to receive(:site_available?).and_return(false)
iedriver.remove
end

it 'raises exception finding latest version' do
expect { iedriver.latest_version }.to raise_error(StandardError, 'Can not reach site')
expect { iedriver.latest_version }.to raise_error(StandardError, update_failed_msg)
end

it 'raises exception downloading' do
expect { iedriver.download }.to raise_error(StandardError, 'Can not reach site')
expect { iedriver.download }.to raise_error(StandardError, update_failed_msg)
end
end
end
8 changes: 6 additions & 2 deletions spec/webdrivers/ms_webdriver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

describe Webdrivers::MSWebdriver do
let(:mswebdriver) { described_class }
let(:update_failed_msg) { /^Update site is unreachable. Try downloading 'MicrosoftWebDriver(.exe)?' manually from (.*)?and place in '(.*)?\.webdrivers'$/ }

it 'downloads mswebdriver' do
mswebdriver.remove
Expand All @@ -15,10 +16,13 @@
end

context 'when offline' do
before { allow(mswebdriver).to receive(:site_available?).and_return(false) }
before do
allow(mswebdriver).to receive(:site_available?).and_return(false)
mswebdriver.remove
end

it 'raises exception downloading' do
expect { mswebdriver.download }.to raise_error(StandardError, 'Can not reach site')
expect { mswebdriver.download }.to raise_error(StandardError, update_failed_msg)
end
end
end