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

Build workers for testing on demand #2018

Merged
merged 6 commits into from
Nov 1, 2023
Merged
Changes from 1 commit
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
68 changes: 58 additions & 10 deletions polkadot/node/core/pvf/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,39 @@ pub fn validate_candidate(
pub fn get_and_check_worker_paths() -> (PathBuf, PathBuf) {
mrcnski marked this conversation as resolved.
Show resolved Hide resolved
// Only needs to be called once for the current process.
static WORKER_PATHS: OnceLock<Mutex<(PathBuf, PathBuf)>> = OnceLock::new();

fn maybe_build_workers(build_prep: bool, build_exec: bool) {
let build_args = match (build_prep, build_exec) {
(true, true) => "build --bin polkadot-prepare-worker --bin polkadot-execute-worker",
(true, false) => "build --bin polkadot-prepare-worker",
(false, true) => "build --bin polkadot-execute-worker",
(false, false) => "",
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let build_args = match (build_prep, build_exec) {
(true, true) => "build --bin polkadot-prepare-worker --bin polkadot-execute-worker",
(true, false) => "build --bin polkadot-prepare-worker",
(false, true) => "build --bin polkadot-execute-worker",
(false, false) => "",
};
let mut build_args = vec!["build"];
if build_prep {
build_args.push("--bin=polkadot-prepare-worker');
}
if build_exec {
build_args.push("--bin=polkadot-execute-worker');
}


if build_args.len() > 0 {
eprintln!("Building workers...");

let mut wd = std::env::current_exe().unwrap();
while !wd.ends_with("polkadot-sdk") {
wd.pop();
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let mut wd = std::env::current_exe().unwrap();
while !wd.ends_with("polkadot-sdk") {
wd.pop();
}

let child = match std::process::Command::new("cargo")
.args(build_args.split(' '))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.args(build_args.split(' '))
.args(build_args)

.stdout(std::process::Stdio::piped())
.current_dir(wd)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.current_dir(wd)
.current_dir(env!("CARGO_MANIFEST_DIR"))

If someone points the target dir to somewhere outside of the repo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice to know! But this might also break if cargo test is not run at project root. I got an idea

.spawn()
{
Ok(child) => child,
Err(err) => panic!("Failed to start cargo build: {}", err),
};

if let Err(err) = child.wait_with_output() {
panic!("Failed to build workers: {}", err);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.spawn()
{
Ok(child) => child,
Err(err) => panic!("Failed to start cargo build: {}", err),
};
if let Err(err) = child.wait_with_output() {
panic!("Failed to build workers: {}", err);
}
.status()
.expect("Failed to run the build program");

}
}

let mutex = WORKER_PATHS.get_or_init(|| {
let mut workers_path = std::env::current_exe().unwrap();
workers_path.pop();
Expand All @@ -71,22 +104,37 @@ pub fn get_and_check_worker_paths() -> (PathBuf, PathBuf) {
let mut execute_worker_path = workers_path.clone();
execute_worker_path.push(EXECUTE_BINARY_NAME);

let mut build_prep = false;
let mut build_exec = false;

// Check that the workers are valid.
if !prepare_worker_path.is_executable() || !execute_worker_path.is_executable() {
panic!("ERROR: Workers do not exist or are not executable. Workers directory: {:?}", workers_path);

if !prepare_worker_path.is_executable() {
eprintln!("WARNING: Prepare worker does not exist or is not executable. Workers directory: {:?}", workers_path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure these warnings have any value, if we build the workers any way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still informative for some cases, let's keep them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which cases do you mean? Like if they get rebuilt and are still not executable? Then this could be a panic, including the command to build them manually.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I meant it could be a bit frustrating if you know you have the workers in place but a build still happens. It'd be nice to clarify that the worker is stale. Even for people who are aware of that, it doesn't hurt to see those messages.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, when I try it I don't see the messages unless cargo test -- --nocapture is passed. Even then, there is so much output that they are easy to miss.

If we can figure out a way to always print the messages, that would be ideal, and I'd also try to make them stand out:

========================
WARNING:

Blah blah workers not available, rebuilding
========================

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why clutter test output with this? This doesn't bring any benefit for the running tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are merely informational, nothing to take action for, it's ok that people miss them I guess.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible for the workers to be rebuilt if the code changed but the version didn't change. In that case the warnings wouldn't be displayed. So these warnings, even if you pass -- --nocapture, are not even consistent. I'd personally vote for dropping them, but I suppose they don't hurt either.

build_prep = true;
}

let worker_version =
get_worker_version(&prepare_worker_path).expect("checked for worker existence");
if worker_version != NODE_VERSION {
panic!("ERROR: Prepare worker version {worker_version} does not match node version {NODE_VERSION}; worker path: {prepare_worker_path:?}");
if !execute_worker_path.is_executable() {
eprintln!("WARNING: Execute worker does not exist or is not executable. Workers directory: {:?}", workers_path);
build_exec = true;
}
let worker_version =
get_worker_version(&execute_worker_path).expect("checked for worker existence");
if worker_version != NODE_VERSION {
panic!("ERROR: Execute worker version {worker_version} does not match node version {NODE_VERSION}; worker path: {execute_worker_path:?}");

if let Ok(ver) = get_worker_version(&prepare_worker_path) {
if ver != NODE_VERSION {
eprintln!("WARNING: Prepare worker version {ver} does not match node version {NODE_VERSION}; worker path: {prepare_worker_path:?}");
build_prep = true;
}
}

if let Ok(ver) = get_worker_version(&execute_worker_path) {
if ver != NODE_VERSION {
eprintln!("WARNING: Execute worker version {ver} does not match node version {NODE_VERSION}; worker path: {execute_worker_path:?}");
build_exec = true;
}
}

maybe_build_workers(build_prep, build_exec);

// We don't want to check against the commit hash because we'd have to always rebuild
// the calling crate on every commit.
eprintln!("WARNING: Workers match the node version, but may have changed in recent commits. Please rebuild them if anything funny happens. Workers path: {workers_path:?}");
Expand Down
Loading