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

fix: windows #2132

Merged
merged 19 commits into from
Jul 4, 2022
Merged

fix: windows #2132

merged 19 commits into from
Jul 4, 2022

Conversation

onbjerg
Copy link
Member

@onbjerg onbjerg commented Jun 27, 2022

After the svm-rs fix we now have new failing tests. Also adds a new test for #2092 and #2085, and will (eventually) fix those bugs

Closes #2078, closes #2092, closes #2085

@onbjerg onbjerg added the L-ignore Log: ignore PR in changelog label Jun 27, 2022
@onbjerg onbjerg force-pushed the onbjerg/windows-integration-tests branch 2 times, most recently from 8aa5c3f to 38e3d6b Compare June 27, 2022 07:55
@onbjerg onbjerg marked this pull request as draft June 27, 2022 07:55
@onbjerg onbjerg force-pushed the onbjerg/windows-integration-tests branch from 38e3d6b to 2c83fd1 Compare June 27, 2022 07:58
@onbjerg
Copy link
Member Author

onbjerg commented Jun 27, 2022

Upon more investigation it seems the tests fail because we try to match run tests using ArtifactId::identifier as keys, and on Windows these use , whereas on other platforms they use /

@mattsse
Copy link
Member

mattsse commented Jun 27, 2022

using ArtifactId::identifier as keys,

Where exactly? Where do we perform comparisons with "identifiers"?

@onbjerg
Copy link
Member Author

onbjerg commented Jun 27, 2022

@mattsse In MultiContractRunner we key the results sent back to the test reporter by ArtifactId::identifier here:

let identifier = id.identifier();

In the multirunner tests we collect these results in a BTreeMap and try to compare them with what we expect. The expected results are stored in a BTreeMap, again, keyed by ArtifactId::identifier:

"core/FailingSetup.t.sol:FailingSetupTest",

@mattsse
Copy link
Member

mattsse commented Jun 27, 2022

I see, but this is only an issue with the test, right? because on windows, everything should be \?

we can update the tests with either format!("src{}..", MAIN_SEPARATOR)

See https://doc.rust-lang.org/std/path/constant.MAIN_SEPARATOR.html

I think it's also worthwhile adding a function to ArtifactId that does convert slashes, via path-slash crate

@onbjerg
Copy link
Member Author

onbjerg commented Jun 27, 2022

If that's the case then I think that might be our bug for the other Windows issues - we use dunce::canonicalize heavily which will turn \ into / but that's not the case for some ethers-rs stuff. At least that's my current thinking, will have to investigate more. Ideally we'd support both but that also means settling on one version. Afaik Windows supports both

@onbjerg onbjerg force-pushed the onbjerg/windows-integration-tests branch 6 times, most recently from 89b8184 to 2bb6cac Compare June 28, 2022 15:37
@onbjerg
Copy link
Member Author

onbjerg commented Jun 28, 2022

Currently failing things:

  • ANSI escape sequences in our snapshots, but those are not present on Windows
  • Cast crashes because of a stack overflow for some reason (Forge doesn't lol?)
  • Slashes in remappings are wrong
  • Slashes in some snapshots are wrong (from ArtifactId::identifier)
  • Some forge script integration tests fail with "The system cannot move the file to a different disk drive. (os error 17)" whatever that means
  • One contract won't compile(???)

@onbjerg onbjerg force-pushed the onbjerg/windows-integration-tests branch from c1137c6 to 8236acc Compare June 28, 2022 16:13
@onbjerg onbjerg mentioned this pull request Jun 29, 2022
2 tasks
@@ -99,7 +99,7 @@ impl ScriptArgs {

let mut extra_info = ExtraLinkingInfo {
no_target_name,
target_fname,
target_fname: target_fname.clone(),
Copy link
Member Author

Choose a reason for hiding this comment

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

This clone is for a better error message further down.. Once we clean up linking we should consider cleaning up the targetting logic in script as well (and other commands that take <path>:<name>)

Comment on lines +148 to +151
let (path, name) = extra
.target_fname
.rsplit_once(':')
.expect("The target specifier is malformed.");
Copy link
Member Author

Choose a reason for hiding this comment

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

Turns out the bug was staring us in the face all along - on Windows paths obviously contain : so the path we compared with in this branch was literally just the drive letter on Windows lmao

Copy link
Member

Choose a reason for hiding this comment

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

omg

@@ -210,22 +211,25 @@ impl ScriptArgs {

// We received `contract_path:contract_name`
if let Some(path) = contract.path {
let path = dunce::canonicalize(&path)?;
let path =
dunce::canonicalize(&path).wrap_err("Could not canonicalize the target path")?;
Copy link
Member Author

Choose a reason for hiding this comment

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

Some error message improvements

cli/src/utils.rs Outdated
let is_windows = cfg!(windows) && !Paint::enable_windows_ascii();
let env_colour_disabled = std::env::var("NO_COLOR").is_ok();
if is_windows || env_colour_disabled {
if is_test || is_windows || env_colour_disabled {
Copy link
Member Author

Choose a reason for hiding this comment

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

Windows doesn't support color out of the box so instead of replacing every ANSI escape code in our fixtures I just opted to disable colors in tests. I think this is OK, if the colors are off it's not critical and we'd know easily anyway

});

impl OutputExt for process::Output {
#[track_caller]
fn stdout_matches_path(&self, expected_path: impl AsRef<Path>) -> &Self {
let expected = fs::read_to_string(expected_path).unwrap();
let expected = IGNORE_IN_FIXTURES.replace_all(&expected, "");
let expected = IGNORE_IN_FIXTURES.replace_all(&expected, "").replace('\\', "/");
Copy link
Member Author

Choose a reason for hiding this comment

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

This is because ArtifactId::identifier does not contain a canonicalized path

Comment on lines +699 to +704
format!(
"{}={}/",
src,
dest.trim_end_matches('/')
.replace('/', std::str::from_utf8(&[std::path::MAIN_SEPARATOR as u8]).unwrap())
)
Copy link
Member Author

Choose a reason for hiding this comment

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

Remappings from Config on Windows seem to use Windows paths, except if part of the path is from another remapping (see the config tests for examples).

The remappings we use to compare in tests however are not canonicalized. I'm not sure what the best fix is given how flexible remappings are

forgetest!(canhandle_direct_imports_into_src, |prj: TestProject, mut cmd: TestCommand| {
// Tests that direct import paths are handled correctly
//
// NOTE(onbjerg): Disabled for Windows -- for some reason solc fails with a bogus error message
Copy link
Member Author

Choose a reason for hiding this comment

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

I really have NO IDEA at all what is going on here. "Invalid implicit conversion from struct Bar memory to struct Bar memory"????

Copy link
Member

Choose a reason for hiding this comment

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

lol that makes no sense lol
let's keep this ignored for windows

"nested/=lib/nested-lib/lib/nested/".parse().unwrap(),
// NOTE(onbjerg): For some reason a part of this remapping was not normalized on
// Windows
format!("{}another-lib/src/", remapping_str("another-lib/", "lib/nested-lib/lib/"))
Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure what's going on here... I think it might be because the path contains other remappings? It's a bit hard to follow

"nested/=lib/nested-lib/lib/nested/".parse().unwrap(),
// NOTE(onbjerg): For some reason a part of this remapping was not normalized on
// Windows
format!(
Copy link
Member Author

Choose a reason for hiding this comment

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

Same as above

struct PrettyString(String);

impl PartialEq for PrettyString {
fn eq(&self, other: &PrettyString) -> bool {
self.0.lines().eq(other.0.lines())
Copy link
Member Author

Choose a reason for hiding this comment

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

Avoids having to replace \r\n with \n

@onbjerg onbjerg changed the title test: fix windows integration tests test: fix windows Jul 3, 2022
@onbjerg onbjerg changed the title test: fix windows fix: windows Jul 3, 2022
@onbjerg onbjerg added T-bug Type: bug and removed L-ignore Log: ignore PR in changelog labels Jul 3, 2022
@onbjerg
Copy link
Member Author

onbjerg commented Jul 3, 2022

Finally! I reverted the workflow back to its original state(ish), but a successful run can be found here: https://github.com/foundry-rs/foundry/runs/7165826844 (note: long testing time is cus I accidentally removed the cache step lol)

@onbjerg onbjerg marked this pull request as ready for review July 3, 2022 02:50
let testdata = format!("{}/../../testdata", env!("CARGO_MANIFEST_DIR"));
std::fs::hard_link(
std::fs::copy(
Copy link
Member Author

Choose a reason for hiding this comment

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

Hard links from some non-temp directory to a temp directory is considered a violation of filesystem boundaries on Windows, so we have to copy instead 🙄

@onbjerg onbjerg force-pushed the onbjerg/windows-integration-tests branch from 5912625 to ca7b393 Compare July 3, 2022 13:20
@onbjerg onbjerg force-pushed the onbjerg/windows-integration-tests branch from fcfa280 to bcdfc87 Compare July 3, 2022 14:35
Copy link
Member

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

awesome!

not sure what to do about the remapping_str.
perhaps easiest solution would be using path_slash::PathBufExt to convert all slashes in the remappings?

rustflags = [
# Increases the stack size to 10MB, which is
# in line with Linux (whereas default for Windows is 1MB)
"-C", "link-arg=/STACK:10000000",
Copy link
Member

Choose a reason for hiding this comment

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

TIL

///
/// NOTE: This probably should be unnecessary, and remappings should probably
/// be canonicalized.
pub fn remapping_str(src: &str, dest: &str) -> String {
Copy link
Member

Choose a reason for hiding this comment

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

should we use paths-slash crate here instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

I wonder if we should do that in ethers-solc instead - not sure if using / would break anything internally, but I think at a minimum it would be safe to use / in Display?

Copy link
Member

Choose a reason for hiding this comment

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

that makes sense!

forgetest!(canhandle_direct_imports_into_src, |prj: TestProject, mut cmd: TestCommand| {
// Tests that direct import paths are handled correctly
//
// NOTE(onbjerg): Disabled for Windows -- for some reason solc fails with a bogus error message
Copy link
Member

Choose a reason for hiding this comment

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

lol that makes no sense lol
let's keep this ignored for windows

@gakonst
Copy link
Member

gakonst commented Jul 3, 2022

High level lgtm. Wonder if we should think about it more or ship it and let Windows users tell us what works well and what doesn't?

@onbjerg
Copy link
Member Author

onbjerg commented Jul 3, 2022

@gakonst I think ship and figure it out, there are probably other bugs lurking but it's hard to find

@gakonst gakonst merged commit 8e7753d into master Jul 4, 2022
@gakonst gakonst deleted the onbjerg/windows-integration-tests branch July 4, 2022 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-bug Type: bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

forge test --debug crashes: "Target not found?" forge script error Investigate failing windows CI job
3 participants