зеркало из https://github.com/mozilla/fxrecord.git
Build a fake firefox.exe for integration-tests
This commit is contained in:
Родитель
c9dfca73d5
Коммит
3cf57dccc8
|
@ -326,6 +326,13 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fakefox"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"structopt",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
|
@ -684,6 +691,7 @@ dependencies = [
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
"url",
|
"url",
|
||||||
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1402,9 +1410,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structopt"
|
name = "structopt"
|
||||||
version = "0.3.14"
|
version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef"
|
checksum = "6cc388d94ffabf39b5ed5fadddc40147cb21e605f53db6f8f36a625d27489ac5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -1413,9 +1421,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structopt-derive"
|
name = "structopt-derive"
|
||||||
version = "0.4.7"
|
version = "0.4.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a"
|
checksum = "5e2513111825077552a6751dfad9e11ce0fba07d7276a3943a037d7e93e64c5f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
|
"fakefox",
|
||||||
"fxrecorder",
|
"fxrecorder",
|
||||||
"fxrunner",
|
"fxrunner",
|
||||||
"libfxrecord",
|
"libfxrecord",
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "fakefox"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["barret Rennie <barret@mozilla.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
license = "MPL-2.0"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "fakefox"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
structopt = "0.3.17"
|
|
@ -0,0 +1,76 @@
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::process::{exit, Command};
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
/// Mimic the behaviour of `firefox.exe` on Windows.
|
||||||
|
///
|
||||||
|
/// By default, the first run of firefox.exe starts the "Launcher Process", which
|
||||||
|
/// does a bunch of work before re-executing `firefox.exe` as the main (parent)
|
||||||
|
/// process.
|
||||||
|
|
||||||
|
/// Matches the options passed to `firefox.exe` by `fxrunner.
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
struct LauncherOptions {
|
||||||
|
#[structopt(long = "profile")]
|
||||||
|
_profile: String,
|
||||||
|
|
||||||
|
#[structopt(long)]
|
||||||
|
new_instance: bool,
|
||||||
|
|
||||||
|
#[structopt(long)]
|
||||||
|
wait_for_browser: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Options to distinguish main process mode from launcher mode.
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
struct MainOptions {
|
||||||
|
#[structopt(long)]
|
||||||
|
main: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
|
||||||
|
if let Ok(opts) = LauncherOptions::from_iter_safe(&args) {
|
||||||
|
eprintln!("[launcher] args: {:?}", args);
|
||||||
|
// Launcher process.
|
||||||
|
// Launch this executable with different command
|
||||||
|
assert!(opts.wait_for_browser);
|
||||||
|
assert!(opts.new_instance);
|
||||||
|
|
||||||
|
let mut child = Command::new(&args[0])
|
||||||
|
.arg("--main")
|
||||||
|
.spawn()
|
||||||
|
.expect("Could not spawn child");
|
||||||
|
|
||||||
|
eprintln!("[launcher] spawned child process {}", child.id());
|
||||||
|
|
||||||
|
let exit_status = child.wait().expect("wait()");
|
||||||
|
let code = exit_status.code().unwrap();
|
||||||
|
|
||||||
|
eprintln!("[launcher] child exited: {}", code);
|
||||||
|
|
||||||
|
exit(code);
|
||||||
|
} else if let Ok(opts) = MainOptions::from_iter_safe(&args) {
|
||||||
|
if opts.main {
|
||||||
|
eprintln!("[main] args: {:?}", args);
|
||||||
|
assert!(opts.main);
|
||||||
|
|
||||||
|
// Main process.
|
||||||
|
// Just spin the even loop waiting to be terminated.
|
||||||
|
loop {
|
||||||
|
sleep(Duration::from_secs(30));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eprintln!("[fakefox] args: {:?}", args);
|
||||||
|
panic!("[fakefox] not executed as child or parent");
|
||||||
|
}
|
|
@ -166,19 +166,6 @@ mod test {
|
||||||
assert_eq!(stats.top_level_dir, None);
|
assert_eq!(stats.top_level_dir, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
let zip = test_dir.join("firefox.zip");
|
|
||||||
let tempdir = TempDir::new().unwrap();
|
|
||||||
|
|
||||||
let stats = unzip(&zip, tempdir.path()).unwrap();
|
|
||||||
|
|
||||||
let firefox_dir = tempdir.path().join("firefox");
|
|
||||||
assert!(firefox_dir.join("firefox.exe").is_file());
|
|
||||||
|
|
||||||
assert_eq!(stats.extracted, 1);
|
|
||||||
assert_eq!(stats.top_level_dir, Some(PathBuf::from("firefox")));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let zip = test_dir.join("profile.zip");
|
let zip = test_dir.join("profile.zip");
|
||||||
let tempdir = TempDir::new().unwrap();
|
let tempdir = TempDir::new().unwrap();
|
||||||
|
|
|
@ -9,6 +9,9 @@ license = "MPL-2.0"
|
||||||
name = "integration-tests"
|
name = "integration-tests"
|
||||||
path = "src/test.rs"
|
path = "src/test.rs"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
zip = "0.5.6"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_matches = "1.3.0"
|
assert_matches = "1.3.0"
|
||||||
async-trait = "0.1.36"
|
async-trait = "0.1.36"
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
use zip::write::FileOptions;
|
||||||
|
use zip::ZipWriter;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// We need to build fakefox in a separate target directory, or else nested
|
||||||
|
// cargo build will hang forever waiting for a lock on the target directory.
|
||||||
|
let fakefox_target_path = env::current_dir()
|
||||||
|
.expect("no cwd")
|
||||||
|
.parent()
|
||||||
|
.expect("no parent diorectory")
|
||||||
|
.join("target")
|
||||||
|
.join("nested");
|
||||||
|
|
||||||
|
let cargo = env::var("CARGO").expect("no CARGO during cargo build");
|
||||||
|
let cargo_status = Command::new(&cargo)
|
||||||
|
.args(&["build", "-p", "fakefox", "--target-dir"])
|
||||||
|
.arg(&fakefox_target_path)
|
||||||
|
.status()
|
||||||
|
.expect("could not execute `cargo build -p fakefox`.");
|
||||||
|
assert!(
|
||||||
|
cargo_status.success(),
|
||||||
|
"Failed to run `cargo build -p fakefox`."
|
||||||
|
);
|
||||||
|
|
||||||
|
let out_dir = env::var("OUT_DIR").expect("no OUT_DIR during cargo build");
|
||||||
|
let out_dir = Path::new(&out_dir);
|
||||||
|
|
||||||
|
let fakefox_path = fakefox_target_path.join("debug").join("fakefox.exe");
|
||||||
|
let zip_path = out_dir.join("firefox.zip");
|
||||||
|
|
||||||
|
let mut zip_file = File::create(&zip_path).expect("could not create firefox.zip");
|
||||||
|
let mut fakefox_file = File::open(&fakefox_path).expect("could not open fakefox.exe");
|
||||||
|
|
||||||
|
let mut zip = ZipWriter::new(&mut zip_file);
|
||||||
|
zip.add_directory("firefox", FileOptions::default())
|
||||||
|
.unwrap();
|
||||||
|
zip.start_file("firefox/firefox.exe", FileOptions::default())
|
||||||
|
.unwrap();
|
||||||
|
io::copy(&mut fakefox_file, &mut zip).unwrap();
|
||||||
|
zip.finish().unwrap();
|
||||||
|
|
||||||
|
println!("wrote firefox.zip to {}", zip_path.display());
|
||||||
|
}
|
|
@ -18,7 +18,7 @@ use libfxrunner::taskcluster::Taskcluster;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
use crate::util::{test_dir, touch, AssertInvoked};
|
use crate::util::{firefox_zip_path, test_dir, AssertInvoked};
|
||||||
|
|
||||||
/// The only valid session ID for TestSessionManager.
|
/// The only valid session ID for TestSessionManager.
|
||||||
pub const VALID_SESSION_ID: &str = "REQUESTID";
|
pub const VALID_SESSION_ID: &str = "REQUESTID";
|
||||||
|
@ -80,7 +80,7 @@ impl Taskcluster for TestTaskcluster {
|
||||||
}
|
}
|
||||||
Some(TaskclusterFailureMode::BadZip) => test_dir().join("test.zip"),
|
Some(TaskclusterFailureMode::BadZip) => test_dir().join("test.zip"),
|
||||||
Some(TaskclusterFailureMode::NotZip) => test_dir().join("README.md"),
|
Some(TaskclusterFailureMode::NotZip) => test_dir().join("README.md"),
|
||||||
None => test_dir().join("firefox.zip"),
|
None => firefox_zip_path(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let dest = download_dir.join("firefox.zip");
|
let dest = download_dir.join("firefox.zip");
|
||||||
|
@ -289,12 +289,8 @@ impl SessionManager for TestSessionManager {
|
||||||
fs::create_dir(&session_info.path.join("profile"))
|
fs::create_dir(&session_info.path.join("profile"))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
fs::create_dir(&session_info.path.join("firefox"))
|
|
||||||
.await
|
libfxrunner::zip::unzip(&firefox_zip_path(), &session_info.path).unwrap();
|
||||||
.unwrap();
|
|
||||||
touch(&session_info.path.join("firefox").join("firefox.exe"))
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
*self.handle.last_session_info.lock().unwrap() = Some(session_info.clone());
|
*self.handle.last_session_info.lock().unwrap() = Some(session_info.clone());
|
||||||
Ok(session_info)
|
Ok(session_info)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, Read};
|
use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
/// A test helper that is used to assert an operation either occurred or did not
|
/// A test helper that is used to assert an operation either occurred or did not
|
||||||
|
@ -50,6 +50,11 @@ pub fn test_dir() -> PathBuf {
|
||||||
.join("test")
|
.join("test")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the path of the build-generated `firefox.zip`.
|
||||||
|
pub fn firefox_zip_path() -> PathBuf {
|
||||||
|
PathBuf::from(env!("OUT_DIR")).join("firefox.zip")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn directory_is_empty(path: &Path) -> bool {
|
pub fn directory_is_empty(path: &Path) -> bool {
|
||||||
path.read_dir()
|
path.read_dir()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -80,12 +85,3 @@ pub fn assert_file_contents_eq(path: &Path, expected: &'static str) {
|
||||||
};
|
};
|
||||||
assert_eq!(contents, expected);
|
assert_eq!(contents, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn touch(path: &Path) -> Result<(), io::Error> {
|
|
||||||
tokio::fs::OpenOptions::new()
|
|
||||||
.create(true)
|
|
||||||
.write(true)
|
|
||||||
.open(path)
|
|
||||||
.await
|
|
||||||
.map(drop)
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,11 +2,6 @@
|
||||||
|
|
||||||
This directory contains artifacts used for testing.
|
This directory contains artifacts used for testing.
|
||||||
|
|
||||||
## firefox.zip
|
|
||||||
|
|
||||||
This is a sample build artifact containing a "Firefox executable" (an empty
|
|
||||||
file) used for mocking Taskcluster responses.
|
|
||||||
|
|
||||||
## profile.zip
|
## profile.zip
|
||||||
|
|
||||||
This file is a sample profile containing some files present in Firefox
|
This file is a sample profile containing some files present in Firefox
|
||||||
|
|
Двоичные данные
test/firefox.zip
Двоичные данные
test/firefox.zip
Двоичный файл не отображается.
Загрузка…
Ссылка в новой задаче