|
| 1 | +use std::hash::Hash; |
1 | 2 | use std::mem::{self, size_of, MaybeUninit};
|
2 | 3 | use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
|
3 | 4 | use std::path::Path;
|
@@ -312,44 +313,197 @@ impl fmt::Debug for SockAddr {
|
312 | 313 | }
|
313 | 314 | }
|
314 | 315 |
|
315 |
| -#[test] |
316 |
| -fn ipv4() { |
317 |
| - use std::net::Ipv4Addr; |
318 |
| - let std = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876); |
319 |
| - let addr = SockAddr::from(std); |
320 |
| - assert!(addr.is_ipv4()); |
321 |
| - assert_eq!(addr.family(), AF_INET as sa_family_t); |
322 |
| - assert_eq!(addr.domain(), Domain::IPV4); |
323 |
| - assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t); |
324 |
| - assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std))); |
325 |
| - assert_eq!(addr.as_socket_ipv4(), Some(std)); |
326 |
| - assert!(addr.as_socket_ipv6().is_none()); |
327 |
| - |
328 |
| - let addr = SockAddr::from(SocketAddr::from(std)); |
329 |
| - assert_eq!(addr.family(), AF_INET as sa_family_t); |
330 |
| - assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t); |
331 |
| - assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std))); |
332 |
| - assert_eq!(addr.as_socket_ipv4(), Some(std)); |
333 |
| - assert!(addr.as_socket_ipv6().is_none()); |
| 316 | +impl PartialEq for SockAddr { |
| 317 | + fn eq(&self, other: &Self) -> bool { |
| 318 | + unsafe { |
| 319 | + let these_bytes: &[u8] = any_as_u8_slice(&self.storage, self.len as usize); |
| 320 | + let those_bytes: &[u8] = any_as_u8_slice(&other.storage, other.len as usize); |
| 321 | + these_bytes == those_bytes |
| 322 | + } |
| 323 | + } |
| 324 | +} |
| 325 | + |
| 326 | +impl Eq for SockAddr {} |
| 327 | + |
| 328 | +impl Hash for SockAddr { |
| 329 | + fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
| 330 | + unsafe { |
| 331 | + let these_bytes: &[u8] = any_as_u8_slice(&self.storage, self.len as usize); |
| 332 | + these_bytes.hash(state); |
| 333 | + } |
| 334 | + } |
| 335 | +} |
| 336 | + |
| 337 | +unsafe fn any_as_u8_slice<T: Sized>(p: &T, size: usize) -> &[u8] { |
| 338 | + ::std::slice::from_raw_parts((p as *const T) as *const u8, size) |
334 | 339 | }
|
335 | 340 |
|
336 |
| -#[test] |
337 |
| -fn ipv6() { |
338 |
| - use std::net::Ipv6Addr; |
339 |
| - let std = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12); |
340 |
| - let addr = SockAddr::from(std); |
341 |
| - assert!(addr.is_ipv6()); |
342 |
| - assert_eq!(addr.family(), AF_INET6 as sa_family_t); |
343 |
| - assert_eq!(addr.domain(), Domain::IPV6); |
344 |
| - assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t); |
345 |
| - assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std))); |
346 |
| - assert!(addr.as_socket_ipv4().is_none()); |
347 |
| - assert_eq!(addr.as_socket_ipv6(), Some(std)); |
348 |
| - |
349 |
| - let addr = SockAddr::from(SocketAddr::from(std)); |
350 |
| - assert_eq!(addr.family(), AF_INET6 as sa_family_t); |
351 |
| - assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t); |
352 |
| - assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std))); |
353 |
| - assert!(addr.as_socket_ipv4().is_none()); |
354 |
| - assert_eq!(addr.as_socket_ipv6(), Some(std)); |
| 341 | +#[cfg(test)] |
| 342 | +mod tests { |
| 343 | + use super::*; |
| 344 | + |
| 345 | + #[test] |
| 346 | + fn ipv4() { |
| 347 | + use std::net::Ipv4Addr; |
| 348 | + let std = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876); |
| 349 | + let addr = SockAddr::from(std); |
| 350 | + assert!(addr.is_ipv4()); |
| 351 | + assert_eq!(addr.family(), AF_INET as sa_family_t); |
| 352 | + assert_eq!(addr.domain(), Domain::IPV4); |
| 353 | + assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t); |
| 354 | + assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std))); |
| 355 | + assert_eq!(addr.as_socket_ipv4(), Some(std)); |
| 356 | + assert!(addr.as_socket_ipv6().is_none()); |
| 357 | + |
| 358 | + let addr = SockAddr::from(SocketAddr::from(std)); |
| 359 | + assert_eq!(addr.family(), AF_INET as sa_family_t); |
| 360 | + assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t); |
| 361 | + assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std))); |
| 362 | + assert_eq!(addr.as_socket_ipv4(), Some(std)); |
| 363 | + assert!(addr.as_socket_ipv6().is_none()); |
| 364 | + } |
| 365 | + |
| 366 | + #[test] |
| 367 | + fn ipv6() { |
| 368 | + use std::net::Ipv6Addr; |
| 369 | + let std = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12); |
| 370 | + let addr = SockAddr::from(std); |
| 371 | + assert!(addr.is_ipv6()); |
| 372 | + assert_eq!(addr.family(), AF_INET6 as sa_family_t); |
| 373 | + assert_eq!(addr.domain(), Domain::IPV6); |
| 374 | + assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t); |
| 375 | + assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std))); |
| 376 | + assert!(addr.as_socket_ipv4().is_none()); |
| 377 | + assert_eq!(addr.as_socket_ipv6(), Some(std)); |
| 378 | + |
| 379 | + let addr = SockAddr::from(SocketAddr::from(std)); |
| 380 | + assert_eq!(addr.family(), AF_INET6 as sa_family_t); |
| 381 | + assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t); |
| 382 | + assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std))); |
| 383 | + assert!(addr.as_socket_ipv4().is_none()); |
| 384 | + assert_eq!(addr.as_socket_ipv6(), Some(std)); |
| 385 | + } |
| 386 | + |
| 387 | + #[test] |
| 388 | + fn ipv4_eq() { |
| 389 | + use std::net::Ipv4Addr; |
| 390 | + |
| 391 | + let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876); |
| 392 | + let std2 = SocketAddrV4::new(Ipv4Addr::new(5, 6, 7, 8), 8765); |
| 393 | + |
| 394 | + test_eq( |
| 395 | + SockAddr::from(std1), |
| 396 | + SockAddr::from(std1), |
| 397 | + SockAddr::from(std2), |
| 398 | + ); |
| 399 | + } |
| 400 | + |
| 401 | + #[test] |
| 402 | + fn ipv4_hash() { |
| 403 | + use std::net::Ipv4Addr; |
| 404 | + |
| 405 | + let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876); |
| 406 | + let std2 = SocketAddrV4::new(Ipv4Addr::new(5, 6, 7, 8), 8765); |
| 407 | + |
| 408 | + test_hash( |
| 409 | + SockAddr::from(std1), |
| 410 | + SockAddr::from(std1), |
| 411 | + SockAddr::from(std2), |
| 412 | + ); |
| 413 | + } |
| 414 | + |
| 415 | + #[test] |
| 416 | + fn ipv6_eq() { |
| 417 | + use std::net::Ipv6Addr; |
| 418 | + |
| 419 | + let std1 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12); |
| 420 | + let std2 = SocketAddrV6::new(Ipv6Addr::new(3, 4, 5, 6, 7, 8, 9, 0), 7654, 13, 14); |
| 421 | + |
| 422 | + test_eq( |
| 423 | + SockAddr::from(std1), |
| 424 | + SockAddr::from(std1), |
| 425 | + SockAddr::from(std2), |
| 426 | + ); |
| 427 | + } |
| 428 | + |
| 429 | + #[test] |
| 430 | + fn ipv6_hash() { |
| 431 | + use std::net::Ipv6Addr; |
| 432 | + |
| 433 | + let std1 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12); |
| 434 | + let std2 = SocketAddrV6::new(Ipv6Addr::new(3, 4, 5, 6, 7, 8, 9, 0), 7654, 13, 14); |
| 435 | + |
| 436 | + test_hash( |
| 437 | + SockAddr::from(std1), |
| 438 | + SockAddr::from(std1), |
| 439 | + SockAddr::from(std2), |
| 440 | + ); |
| 441 | + } |
| 442 | + |
| 443 | + #[test] |
| 444 | + fn ipv4_ipv6_eq() { |
| 445 | + use std::net::Ipv4Addr; |
| 446 | + use std::net::Ipv6Addr; |
| 447 | + |
| 448 | + let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876); |
| 449 | + let std2 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12); |
| 450 | + |
| 451 | + test_eq( |
| 452 | + SockAddr::from(std1), |
| 453 | + SockAddr::from(std1), |
| 454 | + SockAddr::from(std2), |
| 455 | + ); |
| 456 | + |
| 457 | + test_eq( |
| 458 | + SockAddr::from(std2), |
| 459 | + SockAddr::from(std2), |
| 460 | + SockAddr::from(std1), |
| 461 | + ); |
| 462 | + } |
| 463 | + |
| 464 | + #[test] |
| 465 | + fn ipv4_ipv6_hash() { |
| 466 | + use std::net::Ipv4Addr; |
| 467 | + use std::net::Ipv6Addr; |
| 468 | + |
| 469 | + let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876); |
| 470 | + let std2 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12); |
| 471 | + |
| 472 | + test_hash( |
| 473 | + SockAddr::from(std1), |
| 474 | + SockAddr::from(std1), |
| 475 | + SockAddr::from(std2), |
| 476 | + ); |
| 477 | + |
| 478 | + test_hash( |
| 479 | + SockAddr::from(std2), |
| 480 | + SockAddr::from(std2), |
| 481 | + SockAddr::from(std1), |
| 482 | + ); |
| 483 | + } |
| 484 | + |
| 485 | + #[allow(clippy::eq_op)] // allow a0 == a0 check |
| 486 | + fn test_eq(a0: SockAddr, a1: SockAddr, b: SockAddr) { |
| 487 | + assert!(a0 == a0); |
| 488 | + assert!(a0 == a1); |
| 489 | + assert!(a1 == a0); |
| 490 | + assert!(a0 != b); |
| 491 | + assert!(b != a0); |
| 492 | + } |
| 493 | + |
| 494 | + fn test_hash(a0: SockAddr, a1: SockAddr, b: SockAddr) { |
| 495 | + assert!(calculate_hash(&a0) == calculate_hash(&a0)); |
| 496 | + assert!(calculate_hash(&a0) == calculate_hash(&a1)); |
| 497 | + // technically unequal values can have the same hash, in this case x != z and both have different hashes |
| 498 | + assert!(calculate_hash(&a0) != calculate_hash(&b)); |
| 499 | + } |
| 500 | + |
| 501 | + fn calculate_hash(x: &SockAddr) -> u64 { |
| 502 | + use std::collections::hash_map::DefaultHasher; |
| 503 | + use std::hash::Hasher; |
| 504 | + |
| 505 | + let mut hasher = DefaultHasher::new(); |
| 506 | + x.hash(&mut hasher); |
| 507 | + hasher.finish() |
| 508 | + } |
355 | 509 | }
|
0 commit comments