Skip to content

feat: add self replacer integration tests#2401

Open
alvarocabanas wants to merge 8 commits intomainfrom
feat/NR_537430_self_replacement_testing_harness
Open

feat: add self replacer integration tests#2401
alvarocabanas wants to merge 8 commits intomainfrom
feat/NR_537430_self_replacement_testing_harness

Conversation

@alvarocabanas
Copy link
Copy Markdown
Contributor

@alvarocabanas alvarocabanas commented Apr 9, 2026

Summary

Adds comprehensive integration tests for the self-replacer crate that compile and run real binaries to verify self-replacement behavior works correctly on both Unix and Windows platforms.

Test Coverage:

Common tests (Unix + Windows):

  • ✅ Full self-replacement workflow with version verification
  • ✅ Rollback on invalid path
  • ✅ Backup file creation with correct content

Unix-specific tests:

  • ✅ Permission preservation during replacement

Uses Cargo's examples/ directory to provide a pre-built test binary that:

  • Reports its own content hash for verification
  • Performs self-replacement when invoked with --replace flag
  • Eliminates runtime compilation for ~20x faster tests (21s → 1s)

Structure

self-replacer/
├── examples/
│ └── self_replacing_binary.rs # Pre-built example binary
└── tests/
├── integration_tests.rs # All integration tests
└── test_helpers.rs # Helper functions (copy/modify binary)

@alvarocabanas alvarocabanas requested a review from a team as a code owner April 9, 2026 14:56
@alvarocabanas alvarocabanas force-pushed the feat/NR_537430_self_replacement_testing_harness branch 7 times, most recently from 59c162c to 5a86f7b Compare April 9, 2026 16:30
Copy link
Copy Markdown
Contributor

@DavSanchez DavSanchez left a comment

Choose a reason for hiding this comment

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

Great! Some comments.

@alvarocabanas alvarocabanas force-pushed the feat/NR_537430_self_replacement_testing_harness branch 2 times, most recently from b15ed85 to fa91684 Compare April 10, 2026 07:14
DavSanchez
DavSanchez previously approved these changes Apr 10, 2026
Copy link
Copy Markdown
Contributor

@DavSanchez DavSanchez left a comment

Choose a reason for hiding this comment

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

Looking great to start driving this functionality. Thanks!


// Set specific permissions on v1
let mut perms = fs::metadata(&binary_v1).unwrap().permissions();
perms.set_mode(0o754);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would be nice to have a constant or let binding for this one so it's easier to use down in the code, compare it and document what permission it is.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in last commit.

@alvarocabanas alvarocabanas force-pushed the feat/NR_537430_self_replacement_testing_harness branch from e2ae2a0 to 51e0d3a Compare April 13, 2026 08:51
Copy link
Copy Markdown
Contributor

@sigilioso sigilioso left a comment

Choose a reason for hiding this comment

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

Looks good! Find some additional questions below

Comment on lines +31 to +33
[[example]]
name = "self_replacing_binary"
test = false
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice! Could we add a comment explaining why test = false is needed?

Maybe some comments regarding the purpose of the example (either here or in the example's rust file) would be useful as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in last commit.

backup_path
);

// Verify backup has the original hash
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit:

Suggested change
// Verify backup has the original hash
// Verify that the binary in the backup is the original

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in last commit

Comment on lines +12 to +13
/// This ensures tests work both locally and in CI without requiring a separate build step.
pub fn get_example_binary() -> PathBuf {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Doesn't assert_cmd already take care of binaries in the examples path?

// assert_cmd looks in target/debug/examples/ automatically
    Command::cargo_bin("self_replacing_binary")
        .expect("Example binary 'self_replacing_binary' should exist");

I think that assert_cmd already calls cargo under the hood. Maybe we don't need this helper.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

assert_cmd doesn't work with examples and would need to have this binary in the [[bin]] that is not optimal

@alvarocabanas alvarocabanas requested a review from sigilioso April 13, 2026 10:22
Comment on lines +57 to +64
Command::new(&binary_path)
.assert()
.success()
.stdout(predicate::str::starts_with("HASH:"));

let output2 = Command::new(&binary_path)
.output()
.expect("Failed to get new hash");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This test runs the command two times each. Can't we retrieve the hash and assert on the assert_cmd::Command in the same run? I see there's get_output() that we can call on the Asserts that get generated on calls to assert().

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in last commit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants