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

implements driver caching #104

Merged
merged 1 commit into from
May 8, 2019
Merged
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
7 changes: 6 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
AllCops:
TargetRubyVersion: 2.4.6

require:
- rubocop-rspec
- rubocop-performance
Expand All @@ -21,13 +24,15 @@ Metrics/BlockLength:
- 'spec/**/*'

Metrics/ClassLength:
Max: 102
Max: 116

Metrics/CyclomaticComplexity:
Max: 8

Metrics/AbcSize:
Max: 16
Exclude:
- 'lib/webdrivers/chromedriver.rb'

Style/Documentation:
Enabled: false
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ matrix:
env: RAKE_TASK=spec
- rvm: 2.4.6
env: RAKE_TASK=rubocop
- rvm: jruby-9.2.0.0
- rvm: jruby-9.2.7.0
env: RAKE_TASK=spec
4 changes: 2 additions & 2 deletions lib/webdrivers/chromedriver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def latest_version
# Versions before 70 do not have a LATEST_RELEASE file
return normalize_version('2.41') if release_version < normalize_version('70')

latest_applicable = latest_point_release(release_version)
latest_applicable = with_cache(file_name) { latest_point_release(release_version) }

Webdrivers.logger.debug "Latest version available: #{latest_applicable}"
normalize_version(latest_applicable)
Expand Down Expand Up @@ -73,7 +73,7 @@ def download_url
normalize_version(required_version)
end

file_name = System.platform == 'win' ? 'windows32' : "#{System.platform}64"
file_name = System.platform == 'win' ? 'win32' : "#{System.platform}64"
url = "#{base_url}/#{version}/chromedriver_#{file_name}.zip"
Webdrivers.logger.debug "chromedriver URL: #{url}"
@download_url = url
Expand Down
31 changes: 25 additions & 6 deletions lib/webdrivers/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ class VersionError < StandardError
class << self
attr_accessor :proxy_addr, :proxy_port, :proxy_user, :proxy_pass, :install_dir

attr_writer :cache_time

def cache_time
@cache_time || 0
end

def logger
@logger ||= Webdrivers::Logger.new
end
Expand All @@ -34,6 +40,7 @@ def net_http_ssl_fix
class Common
class << self
attr_writer :required_version
attr_reader :cache_warning

def version
Webdrivers.logger.deprecate("#{self.class}#version", "#{self.class}#required_version")
Expand All @@ -46,7 +53,7 @@ def version=(version)
end

def required_version
Gem::Version.new @required_version
normalize_version @required_version
end

def update
Expand All @@ -67,13 +74,10 @@ def desired_version
desired_version.version.empty? ? latest_version : normalize_version(desired_version)
end

def latest_version
@latest_version ||= downloads.keys.max
end

def remove
@download_url = nil
@latest_version = nil
System.delete "#{System.install_dir}/#{file_name.gsub('.exe', '')}.version"
System.delete driver_path
end

Expand Down Expand Up @@ -120,7 +124,7 @@ def sufficient_binary?
end

def normalize_version(version)
Gem::Version.new(version.to_s)
Gem::Version.new(version&.to_s)
end

def binary_version
Expand All @@ -131,6 +135,21 @@ def binary_version
Webdrivers.logger.debug "No Such File or Directory: #{driver_path}"
nil
end

def with_cache(file_name)
if System.valid_cache?(file_name)
normalize_version System.cached_version(file_name)
else
unless cache_warning
Webdrivers.logger.warn 'Driver caching is turned off in this version, but will be '\
'enabled by default in 4.x. Set the value with `Webdrivers#cache_time=` in seconds'
@cache_warning = true
end
version = yield
System.cache_version(file_name, version)
normalize_version version
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/webdrivers/geckodriver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def current_version
end

def latest_version
@latest_version ||= Gem::Version.new(Network.get_url("#{base_url}/latest")[/[^v]*$/])
@latest_version ||= with_cache(file_name) { normalize_version(Network.get_url("#{base_url}/latest")[/[^v]*$/]) }
end

private
Expand Down
4 changes: 4 additions & 0 deletions lib/webdrivers/iedriver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ def current_version
normalize_version version.match(/IEDriverServer.exe (\d\.\d+\.\d+)/)[1]
end

def latest_version
@latest_version ||= with_cache(file_name) { downloads.keys.max }
end

private

def file_name
Expand Down
21 changes: 20 additions & 1 deletion lib/webdrivers/system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,25 @@ def install_dir
Webdrivers.install_dir || File.expand_path(File.join(ENV['HOME'], '.webdrivers'))
end

def cache_version(file_name, version)
FileUtils.mkdir_p(install_dir) unless File.exist?(install_dir)

File.open("#{install_dir}/#{file_name.gsub('.exe', '')}.version", 'w+') do |file|
file.print(version)
end
end

def cached_version(file_name)
File.open("#{install_dir}/#{file_name.gsub('.exe', '')}.version", 'r', &:read)
end

def valid_cache?(file_name)
file = "#{install_dir}/#{file_name.gsub('.exe', '')}.version"
return false unless File.exist?(file)

Time.now - File.mtime(file) < Webdrivers.cache_time
end

def download(url, target)
FileUtils.mkdir_p(install_dir) unless File.exist?(install_dir)

Expand Down Expand Up @@ -99,7 +118,7 @@ def unzip_file(filename)
zip_file.each do |f|
@top_path ||= f.name
f_path = File.join(Dir.pwd, f.name)
FileUtils.rm_rf(f_path) if File.exist?(f_path)
delete(f_path)
FileUtils.mkdir_p(File.dirname(f_path)) unless File.exist?(File.dirname(f_path))
zip_file.extract(f, f_path)
end
Expand Down
39 changes: 39 additions & 0 deletions spec/webdrivers/chromedriver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,17 @@
expect { chromedriver.update }.to raise_error(Webdrivers::ConnectionError, msg)
end
end

it 'makes a network call if cached driver does not match the browser' do
Webdrivers::System.cache_version('chromedriver', '71.0.3578.137')
allow(chromedriver).to receive(:chrome_version).and_return(Gem::Version.new('73.0.3683.68'))
allow(Webdrivers::Network).to receive(:get).and_return('73.0.3683.68')
allow(Webdrivers::System).to receive(:download)

chromedriver.update

expect(Webdrivers::Network).to have_received(:get).twice
end
end

describe '#current_version' do
Expand Down Expand Up @@ -150,6 +161,34 @@
msg = %r{^Can not reach https://chromedriver.storage.googleapis.com}
expect { chromedriver.latest_version }.to raise_error(Webdrivers::ConnectionError, msg)
end

it 'creates cached file' do
allow(Webdrivers::Network).to receive(:get).and_return('71.0.3578.137')

chromedriver.latest_version
expect(File.exist?("#{Webdrivers::System.install_dir}/chromedriver.version")).to eq true
end

it 'does not make network call if cache is valid' do
allow(Webdrivers).to receive(:cache_time).and_return(3600)
Webdrivers::System.cache_version('chromedriver', '71.0.3578.137')
allow(Webdrivers::Network).to receive(:get)

expect(chromedriver.latest_version).to eq Gem::Version.new('71.0.3578.137')

expect(Webdrivers::Network).not_to have_received(:get)
end

it 'makes a network call if cache is expired' do
Webdrivers::System.cache_version('chromedriver', '71.0.3578.137')
allow(Webdrivers::Network).to receive(:get).and_return('73.0.3683.68')
allow(Webdrivers::System).to receive(:valid_cache?)

expect(chromedriver.latest_version).to eq Gem::Version.new('73.0.3683.68')

expect(Webdrivers::Network).to have_received(:get)
expect(Webdrivers::System).to have_received(:valid_cache?)
end
end

describe '#required_version=' do
Expand Down
31 changes: 30 additions & 1 deletion spec/webdrivers/geckodriver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@

it 'finds the required version from parsed downloads page' do
base = 'https://github.com/mozilla/geckodriver/releases/download'
url = %r{#{base}\/v0\.2\.0\/geckodriver-v0\.2\.0-.*\.tar\.gz}
url = %r{#{base}\/v0\.2\.0\/geckodriver-v0\.2\.0-}

allow(Webdrivers::System).to receive(:download).with(url, geckodriver.driver_path)

Expand Down Expand Up @@ -127,6 +127,35 @@

expect(geckodriver.latest_version).to eq Gem::Version.new('0.24.0')
end

it 'creates cached file' do
allow(Webdrivers::Network).to receive(:get).and_return('0.24.0')

geckodriver.latest_version
expect(File.exist?("#{Webdrivers::System.install_dir}/geckodriver.version")).to eq true
end

it 'does not make network call if cache is valid' do
allow(Webdrivers).to receive(:cache_time).and_return(3600)
Webdrivers::System.cache_version('geckodriver', '0.23.0')
allow(Webdrivers::Network).to receive(:get)

expect(geckodriver.latest_version).to eq Gem::Version.new('0.23.0')

expect(Webdrivers::Network).not_to have_received(:get)
end

it 'makes a network call if cache is expired' do
Webdrivers::System.cache_version('geckodriver', '0.23.0')
url = 'https://github.com/mozilla/geckodriver/releases/tag/v0.24.0'
allow(Webdrivers::Network).to receive(:get_url).and_return(url)
allow(Webdrivers::System).to receive(:valid_cache?)

expect(geckodriver.latest_version).to eq Gem::Version.new('0.24.0')

expect(Webdrivers::Network).to have_received(:get_url)
expect(Webdrivers::System).to have_received(:valid_cache?)
end
end

describe '#required_version=' do
Expand Down
31 changes: 31 additions & 0 deletions spec/webdrivers/i_edriver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,37 @@
it 'correctly parses the downloads page' do
expect(iedriver.send(:downloads)).not_to be_empty
end

it 'creates cached file' do
allow(Webdrivers::Network).to receive(:get).and_return('3.4.0')

iedriver.latest_version
expect(File.exist?("#{Webdrivers::System.install_dir}/IEDriverServer.version")).to eq true
end

it 'does not make network call if cache is valid' do
allow(Webdrivers).to receive(:cache_time).and_return(3600)
Webdrivers::System.cache_version('IEDriverServer', '3.4.0')
allow(Webdrivers::Network).to receive(:get)

expect(iedriver.latest_version).to eq Gem::Version.new('3.4.0')

expect(Webdrivers::Network).not_to have_received(:get)
end

it 'makes a network call if cache is expired' do
Webdrivers::System.cache_version('IEDriverServer', '3.4.0')
base = 'https://selenium-release.storage.googleapis.com/'
hash = {Gem::Version.new('3.4.0') => "#{base}/3.4/IEDriverServer_Win32_3.4.0.zip",
Gem::Version.new('3.5.0') => "#{base}/3.5/IEDriverServer_Win32_3.5.0.zip",
Gem::Version.new('3.5.1') => "#{base}/3.5/IEDriverServer_Win32_3.5.1.zip"}
allow(iedriver).to receive(:downloads).and_return(hash)
allow(Webdrivers::System).to receive(:valid_cache?)

expect(iedriver.latest_version).to eq Gem::Version.new('3.5.1')
expect(iedriver).to have_received(:downloads)
expect(Webdrivers::System).to have_received(:valid_cache?)
end
end

describe '#required_version=' do
Expand Down