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

Select correct webdriver version #706

Merged
merged 2 commits into from
Sep 9, 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
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ chrono = "0.4.6"
assert_cmd = "0.11"
lazy_static = "1.1.0"
predicates = "1.0.0"
serial_test = "0.2"
serial_test_derive = "0.2"
tempfile = "3"

[features]
Expand Down
4 changes: 4 additions & 0 deletions RELEASE_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ This is a list of the things that need to happen during a release.
1. Create a new branch "#.#.#" where "#.#.#" is the release's version.
1. Add this release to the `CHANGELOG.md`. Use the structure of previous
entries.
1. Update `DEFAULT_CHROMEDRIVER_VERSION` in `chromedriver.rs`.
Version is the response of `https://chromedriver.storage.googleapis.com/LATEST_RELEASE`.
1. Update `DEFAULT_GECKODRIVER_VERSION` in `geckodriver.rs`.
Version is the name of the latest tag - `https://github.com/mozilla/geckodriver/releases/latest`.
1. Update the version in `Cargo.toml`.
1. Update the version number and date in `docs/index.html`.
1. Run `cargo update`.
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub mod manifest;
pub mod npm;
pub mod progressbar;
pub mod readme;
pub mod stamps;
pub mod target;
pub mod test;
pub mod wasm_opt;
Expand Down
58 changes: 58 additions & 0 deletions src/stamps.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//! Key-value store in `*.stamps` file.

use failure::{self, ResultExt};
use std::{env, fs, path::PathBuf};

/// Get a value corresponding to the key from the JSON value.
///
/// You should use return value of function `read_stamps_file_to_json()` as `json` argument.
pub fn get_stamp_value(
key: impl AsRef<str>,
json: &serde_json::Value,
) -> Result<String, failure::Error> {
json.get(key.as_ref())
.and_then(|value| value.as_str().map(ToOwned::to_owned))
.ok_or_else(|| {
failure::err_msg(format!("cannot get stamp value for key '{}'", key.as_ref()))
})
}

/// Save the key-value pair to the store.
pub fn save_stamp_value(
key: impl Into<String>,
value: impl AsRef<str>,
) -> Result<(), failure::Error> {
let mut json = read_stamps_file_to_json().unwrap_or_else(|_| serde_json::Map::new().into());

let stamps = json
.as_object_mut()
.ok_or_else(|| failure::err_msg("stamps file doesn't contain JSON object"))?;
stamps.insert(key.into(), value.as_ref().into());

write_to_stamps_file(json)
}

/// Get the path of the `*.stamps` file that is used as the store.
pub fn get_stamps_file_path() -> Result<PathBuf, failure::Error> {
let path = env::current_exe()
.map(|path| path.with_extension("stamps"))
.context("cannot get stamps file path")?;
Ok(path)
}

/// Read `*.stamps` file and convert its content to the JSON value.
pub fn read_stamps_file_to_json() -> Result<serde_json::Value, failure::Error> {
let stamps_file_path = get_stamps_file_path()?;
let stamps_file_content =
fs::read_to_string(stamps_file_path).context("cannot find or read stamps file")?;
let json: serde_json::Value = serde_json::from_str(&stamps_file_content)
.context("stamps file doesn't contain valid JSON")?;
Ok(json)
}

fn write_to_stamps_file(json: serde_json::Value) -> Result<(), failure::Error> {
let stamps_file_path = get_stamps_file_path()?;
let pretty_json = serde_json::to_string_pretty(&json).context("JSON serialization failed")?;
fs::write(stamps_file_path, pretty_json).context("cannot write to stamps file")?;
Ok(())
}
114 changes: 21 additions & 93 deletions src/test/webdriver.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
//! Getting WebDriver client binaries.

mod chromedriver;
mod geckodriver;
mod safaridriver;

use binary_install::Cache;
use failure;
use install::InstallMode;
use std::path::PathBuf;
use target;
use PBAR;

pub use self::{
chromedriver::{get_or_install_chromedriver, install_chromedriver},
geckodriver::{get_or_install_geckodriver, install_geckodriver},
safaridriver::get_safaridriver,
};

// ------ driver helpers ------

fn get_and_notify(
cache: &Cache,
installation_allowed: bool,
Expand All @@ -25,100 +35,18 @@ fn get_and_notify(
}
}

/// Get the path to an existing `chromedriver`, or install it if no existing
/// binary is found.
pub fn get_or_install_chromedriver(
cache: &Cache,
mode: InstallMode,
) -> Result<PathBuf, failure::Error> {
if let Ok(path) = which::which("chromedriver") {
return Ok(path);
}
install_chromedriver(cache, mode.install_permitted())
}

/// Download and install a pre-built `chromedriver` binary.
pub fn install_chromedriver(
cache: &Cache,
installation_allowed: bool,
) -> Result<PathBuf, failure::Error> {
let target = if target::LINUX && target::x86_64 {
"linux64"
} else if target::MACOS && target::x86_64 {
"mac64"
} else if target::WINDOWS {
"win32"
} else {
bail!("chromedriver binaries are unavailable for this target")
};

let url = format!(
"https://chromedriver.storage.googleapis.com/2.46/chromedriver_{}.zip",
target
);
match get_and_notify(cache, installation_allowed, "chromedriver", &url)? {
Some(path) => Ok(path),
None => bail!(
"No cached `chromedriver` binary found, and could not find a global \
`chromedriver` on the `$PATH`. Not installing `chromedriver` because of noinstall \
mode."
),
}
}

/// Get the path to an existing `geckodriver`, or install it if no existing
/// binary is found.
pub fn get_or_install_geckodriver(
cache: &Cache,
mode: InstallMode,
) -> Result<PathBuf, failure::Error> {
if let Ok(path) = which::which("geckodriver") {
return Ok(path);
}
install_geckodriver(cache, mode.install_permitted())
}

/// Download and install a pre-built `geckodriver` binary.
pub fn install_geckodriver(
cache: &Cache,
installation_allowed: bool,
) -> Result<PathBuf, failure::Error> {
let (target, ext) = if target::LINUX && target::x86 {
("linux32", "tar.gz")
} else if target::LINUX && target::x86_64 {
("linux64", "tar.gz")
} else if target::MACOS {
("macos", "tar.gz")
} else if target::WINDOWS && target::x86 {
("win32", "zip")
} else if target::WINDOWS && target::x86_64 {
("win64", "zip")
} else {
bail!("geckodriver binaries are unavailable for this target")
};
struct Collector(Vec<u8>);

let url = format!(
"https://github.com/mozilla/geckodriver/releases/download/v0.24.0/geckodriver-v0.24.0-{}.{}",
target,
ext,
);
match get_and_notify(cache, installation_allowed, "geckodriver", &url)? {
Some(path) => Ok(path),
None => bail!(
"No cached `geckodriver` binary found, and could not find a global `geckodriver` \
on the `$PATH`. Not installing `geckodriver` because of noinstall mode."
),
impl Collector {
pub fn take_content(&mut self) -> Vec<u8> {
// TODO: replace with `std::mem::take` once stable
std::mem::replace(&mut self.0, Vec::default())
}
}

/// Get the path to an existing `safaridriver`.
///
/// We can't install `safaridriver` if an existing one is not found because
/// Apple does not provide pre-built binaries. However, `safaridriver` *should*
/// be present by default.
pub fn get_safaridriver() -> Result<PathBuf, failure::Error> {
match which::which("safaridriver") {
Ok(p) => Ok(p),
Err(_) => bail!("could not find `safaridriver` on the `$PATH`"),
impl curl::easy::Handler for Collector {
fn write(&mut self, data: &[u8]) -> Result<usize, curl::easy::WriteError> {
self.0.extend_from_slice(data);
Ok(data.len())
}
}
Loading