Skip to content
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
2 changes: 2 additions & 0 deletions rb/Steepfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ target :lib do
'lib/selenium/webdriver/bidi/struct.rb',
# The generator + its up-to-date checker are build tooling, not typed runtime code
'lib/selenium/webdriver/bidi/support/**/*.rb',
# Vendored Bazel::Runfiles (rules_ruby#374); build/test tooling, removed when that ships upstream
'lib/bazel/**/*.rb',
# Ignore all spec files
'spec/**/*.rb',
# Ignore line 166 due to UDP RBS issue
Expand Down
8 changes: 8 additions & 0 deletions rb/lib/bazel/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
load("@rules_ruby//ruby:defs.bzl", "rb_library")

package(default_visibility = ["//rb:__subpackages__"])

rb_library(
name = "runfiles",
srcs = ["runfiles.rb"],
)
129 changes: 129 additions & 0 deletions rb/lib/bazel/runfiles.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# frozen_string_literal: true

# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

# Mirrors the Bazel::Runfiles helper in rules_ruby#374; drop this file and depend on
# @rules_ruby//ruby/runfiles once a rules_ruby release ships it.

require 'pathname'

module Bazel
Comment thread
qodo-code-review[bot] marked this conversation as resolved.
# Resolves runtime paths to data dependencies using either a
# manifest file or a runfiles directory.
class Runfiles
def self.create(env = ENV)
manifest_file = env['RUNFILES_MANIFEST_FILE']
runfiles_dir = env['RUNFILES_DIR']

return new(ManifestBased.new(manifest_file)) if manifest_file && !manifest_file.empty?
return new(DirectoryBased.new(runfiles_dir)) if runfiles_dir && !runfiles_dir.empty?

create_from_program_name($PROGRAM_NAME)
end

def self.create_from_program_name(program_name)
if File.exist?("#{program_name}.runfiles_manifest")
new(ManifestBased.new("#{program_name}.runfiles_manifest"))
elsif File.exist?("#{program_name}.runfiles")
new(DirectoryBased.new("#{program_name}.runfiles"))
else
new(DirectoryBased.new(''))
end
end

def initialize(strategy)
@strategy = strategy
end

def rlocation(path)
Comment thread
qodo-code-review[bot] marked this conversation as resolved.
raise ArgumentError, 'path must not be empty' if path.to_s.empty?

return path if Pathname.new(path).absolute?

invalid_path = %r{\A\.\.[/\\]|[/\\]\.\.[/\\]|\A\.[/\\]|[/\\]\.[/\\]|[/\\]\.\z|[/\\][/\\]}
raise ArgumentError, "path is not valid: #{path.inspect}" if path.match?(invalid_path)

raise ArgumentError, "path is absolute without a drive letter: #{path.inspect}" if path.start_with?('\\')

@strategy.rlocation(path)
end

# Resolves paths by looking them up in a runfiles MANIFEST file.
class ManifestBased
def initialize(manifest_path)
@entries = parse_manifest(manifest_path)
end

def rlocation(path)
Comment thread
qodo-code-review[bot] marked this conversation as resolved.
return @entries[path] if @entries.key?(path)

prefix = File.dirname(path)
while prefix != '.' && prefix != '/'
base = @entries[prefix]
return "#{base}#{path[prefix.length..]}" if base && !base.empty?

prefix = File.dirname(prefix)
end

nil
end

private

def parse_manifest(path)
entries = {}
return entries unless File.exist?(path)

File.foreach(path) do |line|
line.chomp!
next if line.empty?

key, value = parse_entry(line)
entries[key] = value
end

entries
end

def parse_entry(line)
escaped = line.delete_prefix!(' ')
key, _, value = line.partition(' ')
return [key, value] unless escaped

[unescape(key), unescape(value)]
end

def unescape(str)
str.gsub(/\\[snb]/, '\s' => ' ', '\n' => "\n", '\b' => '\\')
end
end

# Resolves paths by joining them onto a runfiles directory root.
class DirectoryBased
def initialize(runfiles_dir)
@runfiles_dir = runfiles_dir
end

def rlocation(path)
return nil if @runfiles_dir.empty?

File.join(@runfiles_dir, path)
end
end
end
end
1 change: 1 addition & 0 deletions rb/spec/integration/selenium/webdriver/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ rb_library(
visibility = ["//rb/spec:__subpackages__"],
deps = [
"//rb/lib:selenium-webdriver",
"//rb/lib/bazel:runfiles",
"//rb/lib/selenium:devtools",
"//rb/lib/selenium:server",
"//rb/lib/selenium:webdriver",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
# specific language governing permissions and limitations
# under the License.

require 'bazel/runfiles'

module Selenium
module WebDriver
module SpecSupport
Expand Down Expand Up @@ -128,12 +130,11 @@ def driver_configuration

def driver_path
Comment thread
qodo-code-review[bot] marked this conversation as resolved.
env = {chrome: 'CHROMEDRIVER_BINARY', edge: 'MSEDGEDRIVER_BINARY', firefox: 'GECKODRIVER_BINARY'}[browser]
rlocation(ENV.fetch(env)) if env && ENV.key?(env)
runfiles_path(env) if env
end

def browser_path
env = "#{browser.to_s.upcase}_BINARY"
rlocation(ENV.fetch(env)) if ENV.key?(env)
runfiles_path("#{browser.to_s.upcase}_BINARY")
end

def options_key
Expand All @@ -147,8 +148,12 @@ def w3c_browser_name
def bazel_java
return unless ENV.key?('WD_BAZEL_JAVA_LOCATION')
Comment thread
qodo-code-review[bot] marked this conversation as resolved.

java_path = File.read(File.expand_path(ENV.fetch('WD_BAZEL_JAVA_LOCATION'))).chomp
resolved = rlocation(java_path)
# $(JAVA) is an exec path (external/<repo>/...); strip the prefix to a canonical rlocation
# path, and fall back to the raw path on a lookup miss so we never realpath nil.
java_path = File.read(File.expand_path(ENV.fetch('WD_BAZEL_JAVA_LOCATION'))).chomp.sub(%r{^external/}, '')
resolved = runfiles.rlocation(java_path) || java_path

# Resolve the JDK symlink to its real path to dodge a Windows JVM bug mapping lib\modules.
Platform.windows? && File.exist?(resolved) ? File.realpath(resolved) : resolved
end

Expand Down Expand Up @@ -308,22 +313,22 @@ def chrome_driver(service: nil, **)
service ||= WebDriver::Service.chrome
service.args << '--disable-build-check' if ENV['DISABLE_BUILD_CHECK']
service.args << '--verbose' if WebDriver.logger.debug?
service.executable_path = rlocation(ENV['CHROMEDRIVER_BINARY']) if ENV.key?('CHROMEDRIVER_BINARY')
service.executable_path = runfiles_path('CHROMEDRIVER_BINARY') if ENV.key?('CHROMEDRIVER_BINARY')
WebDriver::Driver.for(:chrome, service: service, **)
end

def edge_driver(service: nil, **)
service ||= WebDriver::Service.edge
service.args << '--disable-build-check' if ENV['DISABLE_BUILD_CHECK']
service.args << '--verbose' if WebDriver.logger.debug?
service.executable_path = rlocation(ENV['MSEDGEDRIVER_BINARY']) if ENV.key?('MSEDGEDRIVER_BINARY')
service.executable_path = runfiles_path('MSEDGEDRIVER_BINARY') if ENV.key?('MSEDGEDRIVER_BINARY')
WebDriver::Driver.for(:edge, service: service, **)
end

def firefox_driver(service: nil, **)
service ||= WebDriver::Service.firefox
service.args.push('--log', 'trace') if WebDriver.logger.debug?
service.executable_path = rlocation(ENV['GECKODRIVER_BINARY']) if ENV.key?('GECKODRIVER_BINARY')
service.executable_path = runfiles_path('GECKODRIVER_BINARY') if ENV.key?('GECKODRIVER_BINARY')
WebDriver::Driver.for(:firefox, service: service, **)
end

Expand All @@ -342,7 +347,7 @@ def safari_preview_driver(**)
def chrome_options(args: [], **opts)
opts[:browser_version] = browser_version
opts[:web_socket_url] = true if ENV['WEBDRIVER_BIDI'] && !opts.key?(:web_socket_url)
opts[:binary] ||= rlocation(ENV['CHROME_BINARY']) if ENV.key?('CHROME_BINARY')
opts[:binary] ||= runfiles_path('CHROME_BINARY') if ENV.key?('CHROME_BINARY')
args << '--headless' if ENV['HEADLESS']
args << '--no-sandbox' unless Platform.windows?
args << '--disable-dev-shm-usage' if GlobalTestEnv.rbe?
Expand All @@ -353,7 +358,7 @@ def chrome_options(args: [], **opts)
def edge_options(args: [], **opts)
opts[:browser_version] = browser_version
opts[:web_socket_url] = true if ENV['WEBDRIVER_BIDI'] && !opts.key?(:web_socket_url)
opts[:binary] ||= rlocation(ENV['EDGE_BINARY']) if ENV.key?('EDGE_BINARY')
opts[:binary] ||= runfiles_path('EDGE_BINARY') if ENV.key?('EDGE_BINARY')
args << '--headless' if ENV['HEADLESS']
args << '--no-sandbox' unless Platform.windows?
args << '--disable-dev-shm-usage' if GlobalTestEnv.rbe?
Expand All @@ -364,7 +369,7 @@ def edge_options(args: [], **opts)
def firefox_options(args: [], **opts)
opts[:browser_version] = browser_version
opts[:web_socket_url] = true if ENV['WEBDRIVER_BIDI'] && !opts.key?(:web_socket_url)
opts[:binary] ||= rlocation(ENV['FIREFOX_BINARY']) if ENV.key?('FIREFOX_BINARY')
opts[:binary] ||= runfiles_path('FIREFOX_BINARY') if ENV.key?('FIREFOX_BINARY')
opts[:unhandled_prompt_behavior] ||= 'ignore'
args << '--headless' if ENV['HEADLESS']
WebDriver::Options.firefox(args: args, **opts)
Expand Down Expand Up @@ -392,20 +397,16 @@ def random_port
sock.close
end

# Resolves a Bazel rootpath to an absolute path using the runfiles tree.
# $(location) returns rootpath like "external/<repo>/<path>" but Bazel 9
# runfiles use rlocation paths like "<repo>/<path>" (no "external/" prefix).
def rlocation(path)
return path if path.nil? || File.exist?(path)

runfiles_dir = ENV.fetch('RUNFILES_DIR', nil)
return path unless runfiles_dir
def runfiles
@runfiles ||= Bazel::Runfiles.create
end

rlocation_path = path.sub(%r{^external/}, '')
resolved = File.join(runfiles_dir, rlocation_path)
return resolved if File.exist?(resolved)
def runfiles_path(env_key)
Comment thread
titusfortner marked this conversation as resolved.
value = ENV.fetch(env_key, nil)
return if value.nil? || value.empty? # a cleared --test_env passes "", which rlocation rejects
return value if File.exist?(value) # honor an on-disk override for local runs without runfiles
Comment thread
titusfortner marked this conversation as resolved.

path
runfiles.rlocation(value) || raise("runfiles could not resolve #{env_key}=#{value.inspect}")
end
end
end # SpecSupport
Expand Down
40 changes: 20 additions & 20 deletions rb/spec/tests.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ BROWSERS = {
"WD_SPEC_DRIVER": "chrome",
} | select({
"@selenium//common:use_pinned_linux_chrome": {
"CHROME_BINARY": "$(location @linux_chrome//:chrome-linux64/chrome)",
"CHROMEDRIVER_BINARY": "$(location @linux_chromedriver//:chromedriver)",
"CHROME_BINARY": "$(rlocationpath @linux_chrome//:chrome-linux64/chrome)",
"CHROMEDRIVER_BINARY": "$(rlocationpath @linux_chromedriver//:chromedriver)",
},
"@selenium//common:use_pinned_macos_chrome": {
"CHROME_BINARY": "$(location @mac_chrome//:Chrome.app)/Contents/MacOS/Chrome",
"CHROMEDRIVER_BINARY": "$(location @mac_chromedriver//:chromedriver)",
"CHROME_BINARY": "$(rlocationpath @mac_chrome//:Chrome.app)/Contents/MacOS/Chrome",
"CHROMEDRIVER_BINARY": "$(rlocationpath @mac_chromedriver//:chromedriver)",
},
"//conditions:default": {},
}) | select({
Expand All @@ -45,12 +45,12 @@ BROWSERS = {
"WD_BROWSER_VERSION": "beta",
} | select({
"@selenium//common:use_pinned_linux_chrome": {
"CHROME_BINARY": "$(location @linux_beta_chrome//:chrome-linux64/chrome)",
"CHROMEDRIVER_BINARY": "$(location @linux_beta_chromedriver//:chromedriver)",
"CHROME_BINARY": "$(rlocationpath @linux_beta_chrome//:chrome-linux64/chrome)",
"CHROMEDRIVER_BINARY": "$(rlocationpath @linux_beta_chromedriver//:chromedriver)",
},
"@selenium//common:use_pinned_macos_chrome": {
"CHROME_BINARY": "$(location @mac_beta_chrome//:Chrome.app)/Contents/MacOS/Chrome",
"CHROMEDRIVER_BINARY": "$(location @mac_beta_chromedriver//:chromedriver)",
"CHROME_BINARY": "$(rlocationpath @mac_beta_chrome//:Chrome.app)/Contents/MacOS/Chrome",
"CHROMEDRIVER_BINARY": "$(rlocationpath @mac_beta_chromedriver//:chromedriver)",
},
"//conditions:default": {},
}) | select({
Expand All @@ -69,12 +69,12 @@ BROWSERS = {
"WD_SPEC_DRIVER": "edge",
} | select({
"@selenium//common:use_pinned_linux_edge": {
"EDGE_BINARY": "$(location @linux_edge//:opt/microsoft/msedge/microsoft-edge)",
"MSEDGEDRIVER_BINARY": "$(location @linux_edgedriver//:msedgedriver)",
"EDGE_BINARY": "$(rlocationpath @linux_edge//:opt/microsoft/msedge/microsoft-edge)",
"MSEDGEDRIVER_BINARY": "$(rlocationpath @linux_edgedriver//:msedgedriver)",
},
"@selenium//common:use_pinned_macos_edge": {
"EDGE_BINARY": "$(location @mac_edge//:Edge.app)/Contents/MacOS/Microsoft\\ Edge",
"MSEDGEDRIVER_BINARY": "$(location @mac_edgedriver//:msedgedriver)",
"EDGE_BINARY": "$(rlocationpath @mac_edge//:Edge.app)/Contents/MacOS/Microsoft\\ Edge",
"MSEDGEDRIVER_BINARY": "$(rlocationpath @mac_edgedriver//:msedgedriver)",
},
"//conditions:default": {},
}) | select({
Expand All @@ -92,12 +92,12 @@ BROWSERS = {
"WD_SPEC_DRIVER": "firefox",
} | select({
"@selenium//common:use_pinned_linux_firefox": {
"FIREFOX_BINARY": "$(location @linux_firefox//:firefox/firefox)",
"GECKODRIVER_BINARY": "$(location @linux_geckodriver//:geckodriver)",
"FIREFOX_BINARY": "$(rlocationpath @linux_firefox//:firefox/firefox)",
"GECKODRIVER_BINARY": "$(rlocationpath @linux_geckodriver//:geckodriver)",
},
"@selenium//common:use_pinned_macos_firefox": {
"FIREFOX_BINARY": "$(location @mac_firefox//:Firefox.app)/Contents/MacOS/firefox",
"GECKODRIVER_BINARY": "$(location @mac_geckodriver//:geckodriver)",
"FIREFOX_BINARY": "$(rlocationpath @mac_firefox//:Firefox.app)/Contents/MacOS/firefox",
"GECKODRIVER_BINARY": "$(rlocationpath @mac_geckodriver//:geckodriver)",
},
"//conditions:default": {},
}) | select({
Expand All @@ -117,12 +117,12 @@ BROWSERS = {
"WD_BROWSER_VERSION": "beta",
} | select({
"@selenium//common:use_pinned_linux_firefox": {
"FIREFOX_BINARY": "$(location @linux_beta_firefox//:firefox/firefox)",
"GECKODRIVER_BINARY": "$(location @linux_geckodriver//:geckodriver)",
"FIREFOX_BINARY": "$(rlocationpath @linux_beta_firefox//:firefox/firefox)",
"GECKODRIVER_BINARY": "$(rlocationpath @linux_geckodriver//:geckodriver)",
},
"@selenium//common:use_pinned_macos_firefox": {
"FIREFOX_BINARY": "$(location @mac_beta_firefox//:Firefox.app)/Contents/MacOS/firefox",
"GECKODRIVER_BINARY": "$(location @mac_geckodriver//:geckodriver)",
"FIREFOX_BINARY": "$(rlocationpath @mac_beta_firefox//:Firefox.app)/Contents/MacOS/firefox",
"GECKODRIVER_BINARY": "$(rlocationpath @mac_geckodriver//:geckodriver)",
},
"//conditions:default": {},
}) | select({
Expand Down