Build a fake firefox.exe for integration-tests

This commit is contained in:
Barret Rennie 2020-09-21 18:11:28 -04:00
Родитель c9dfca73d5
Коммит 3cf57dccc8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4D71D86C09132D72
11 изменённых файлов: 164 добавлений и 40 удалений

16
Cargo.lock сгенерированный
Просмотреть файл

@ -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",

13
fakefox/Cargo.toml Normal file
Просмотреть файл

@ -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"

76
fakefox/src/main.rs Normal file
Просмотреть файл

@ -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

Двоичный файл не отображается.