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

Ensure all tests use unique IP ports #2196

Merged
merged 1 commit into from
Dec 3, 2023
Merged

Conversation

asomers
Copy link
Member

@asomers asomers commented Nov 19, 2023

What does this PR do

Checklist:

  • I have read CONTRIBUTING.md
  • I have written necessary tests and rustdoc comments
  • A change log has been added if this PR modifies nix's API

@SteveLauC
Copy link
Member

There still seems to be tests that are using the same port 8080 in src/sys/socket/addr.rs:

nix/src/sys/socket/addr.rs

Lines 2560 to 2597 in dbdcfed

mod sockaddr_in6 {
use super::*;
use std::str::FromStr;
#[test]
fn display() {
let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
let addr = SockaddrIn6::from_str(s).unwrap();
assert_eq!(s, format!("{addr}"));
}
#[test]
fn size() {
assert_eq!(
mem::size_of::<libc::sockaddr_in6>(),
SockaddrIn6::size() as usize
);
}
#[test]
fn ip() {
let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
let ip = SockaddrIn6::from_str(s).unwrap().ip();
assert_eq!("1234:5678:90ab:cdef::1111:2222", format!("{ip}"));
}
#[test]
// Ensure that we can convert to-and-from std::net variants without change.
fn to_and_from() {
let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
let mut nix_sin6 = SockaddrIn6::from_str(s).unwrap();
nix_sin6.0.sin6_flowinfo = 0x12345678;
nix_sin6.0.sin6_scope_id = 0x9abcdef0;
let std_sin6: std::net::SocketAddrV6 = nix_sin6.into();
assert_eq!(nix_sin6, std_sin6.into());
}
}


BTW, If we want to maintain this state, what about defining some helper type like:

/// Helper type for ensuring all ports used in tests are unique
struct PortAllocator {
    next: AtomicU16,
}

impl PortAllocator {
    pub fn allocate_port(&self) -> u16 {
         self.next.fetch_add(1, Ordering::Relaxed)
    }
}

Though it may be easier to clash (with the ports used on developer's host) comparing to manually-specified ports

recatek added a commit to recatek/nix that referenced this pull request Nov 21, 2023
@asomers
Copy link
Member Author

asomers commented Nov 23, 2023

In the case of the 8080 ports, you'll notice that none of those tests actually bind to the ports in question. So there's no real conflict. Regarding the allocator, I've wondered about that too. But I wonder if the addition of the allocator would obscure the function of some of the tests. Do you think so?

@SteveLauC
Copy link
Member

In the case of the 8080 ports, you'll notice that none of those tests actually bind to the ports in question. So there's no real conflict.

Yeah, that's right, they are not in actual use. I saw the changes in src/sys/socket/addr.rs, which made me think we should also handle such cases, but since they are not in use, let's ignore them

Regarding the allocator, I've wondered about that too. But I wonder if the addition of the allocator would obscure the function of some of the tests. Do you think so?

Emmm, I am not sure about this:D, would you like show me a brief example demostrating your worries?

@asomers
Copy link
Member Author

asomers commented Nov 24, 2023

Regarding the allocator, I've wondered about that too. But I wonder if the addition of the allocator would obscure the function of some of the tests. Do you think so?

Emmm, I am not sure about this:D, would you like show me a brief example demostrating your worries?

I'm just thinking about readability for somebody not highly familiar with this project. Code like this:

let addr = SockaddrIn::from_str("127.0.0.1:1234");

is a lot more obvious than this:

let addr = crate::port_allocator::next();

github-merge-queue bot pushed a commit that referenced this pull request Nov 25, 2023
…rolMessageOwned (#2187)

* Added FreeBSD's SCM_REALTIME and SCM_MONOTONIC into sys::socket::ControlMessageOwned.

* Creating a SocketTimestamp enum for the SO_TS_CLOCK setsockopt for FreeBSD.

* Fixing whitespace

* Fixing CI error on cfg attributes

* Removing legacy doc attributes

* Formatting cleanup

* Updating changelog

* Adding tests for new TsClock setsockopt enum and the two new packet timestamp control messages for FreeBSD

* Replacing an assert_eq with an assert in new tests.

* Removing qemu ignore for new FreeBSD tests

* Giving new FreeBSD timestamping tests each a unique socket

* Updating monotonic packet timestamp test to account for monotonicity

* Moving test ports again to line up with changes in #2196

* Attempting checks again

* Wrapping ptr::read_unaligned calls in unsafe blocks
@SteveLauC
Copy link
Member

I'm just thinking about readability for somebody not highly familiar with this project. Code like this:

Yeah, if we do something like this, we should document it well.

I'm just thinking about readability for somebody not highly familiar with this project. Code like this:

let addr = SockaddrIn::from_str("127.0.0.1:1234");

is a lot more obvious than this:

let addr = crate::port_allocator::next();

Indeed, the old one is clearer, but will we also do this to IP address? It should be something like this if we only do this to ports:

let port = PORT_ALLOCATOR.next();
let addr = SockAddrV4::from_str(&format!("127.0.0.1:{port}")).unwrap();

@asomers
Copy link
Member Author

asomers commented Nov 25, 2023

Either way would work. What do you think is best?

@SteveLauC
Copy link
Member

I think we should add a port allocator because manually maintaining the state is too hard, and conflicts are difficult to catch as well since tests are running concurrently.

For the readability issue, it should not be that bad if we only do this to ports:

let addr = SockAddrV4::from_str(&format!("127.0.0.1:{port}")).unwrap();

BTW, is there any guideline on when a test should be put in src/xxx.rs or test/test_xxx.rs, if not, we should probably make this clear, e.g.,

Tests for public Nix interfaces should all be placed under test, leaving only tests for private stuff within its own module.

@asomers
Copy link
Member Author

asomers commented Nov 26, 2023

BTW, is there any guideline on when a test should be put in src/xxx.rs or test/test_xxx.rs, if not, we should probably make this clear, e.g.,

Not really. Nix has so many contributors; it seems like each has placed tests according to his preference. For me personally I have a rule that I like to use, but it doesn't really apply to Nix.

Tests for public Nix interfaces should all be placed under test, leaving only tests for private stuff within its own module.

👍

@SteveLauC
Copy link
Member

Should we merge this PR? I think it is ok to do that port allocator thing in the future

@asomers
Copy link
Member Author

asomers commented Dec 3, 2023

Should we merge this PR? I think it is ok to do that port allocator thing in the future

Yeah, I think so. Would you approve it please?

@SteveLauC SteveLauC added this pull request to the merge queue Dec 3, 2023
Merged via the queue into nix-rust:master with commit cb56e89 Dec 3, 2023
35 checks passed
@asomers asomers deleted the unique-port branch December 3, 2023 23:16
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.

None yet

2 participants