Skip to content

Commit f1bdaf2

Browse files
ruhi-stripebruceg
andauthored
Check for IP version while determining if two components are conflicting (#14187)
* Update mod.rs * Update mod.rs * Update mod.rs * Update mod.rs * Rework tests using proptest --------- Co-authored-by: Bruce Guenter <[email protected]>
1 parent 1442ca3 commit f1bdaf2

File tree

1 file changed

+111
-96
lines changed

1 file changed

+111
-96
lines changed

src/config/mod.rs

+111-96
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ impl Resource {
282282
for resource in resources {
283283
if let Resource::Port(address, protocol) = &resource {
284284
if address.ip().is_unspecified() {
285-
unspecified.push((key.clone(), address.port(), *protocol));
285+
unspecified.push((key.clone(), *address, *protocol));
286286
}
287287
}
288288

@@ -296,10 +296,13 @@ impl Resource {
296296
// Port with unspecified address will bind to all network interfaces
297297
// so we have to check for all Port resources if they share the same
298298
// port.
299-
for (key, port, protocol0) in unspecified {
299+
for (key, address0, protocol0) in unspecified {
300300
for (resource, components) in resource_map.iter_mut() {
301301
if let Resource::Port(address, protocol) = resource {
302-
if address.port() == port && &protocol0 == protocol {
302+
// IP addresses can either be v4 or v6.
303+
// Therefore we check if the ip version matches, the port matches and if the protocol (TCP/UDP) matches
304+
// when checking for equality.
305+
if &address0 == address && &protocol0 == protocol {
303306
components.insert(key.clone());
304307
}
305308
}
@@ -1259,20 +1262,38 @@ mod acknowledgements_tests {
12591262
}
12601263
}
12611264

1262-
#[cfg(all(test, feature = "sources-stdin", feature = "sinks-console"))]
1265+
#[cfg(test)]
12631266
mod resource_tests {
12641267
use std::{
12651268
collections::{HashMap, HashSet},
1266-
net::{Ipv4Addr, SocketAddr},
1269+
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
12671270
};
12681271

1269-
use indoc::indoc;
1270-
use vector_config::schema::generate_root_schema;
1272+
use proptest::prelude::*;
1273+
1274+
use super::Resource;
1275+
1276+
fn tcp(addr: impl Into<IpAddr>, port: u16) -> Resource {
1277+
Resource::tcp(SocketAddr::new(addr.into(), port))
1278+
}
1279+
1280+
fn udp(addr: impl Into<IpAddr>, port: u16) -> Resource {
1281+
Resource::udp(SocketAddr::new(addr.into(), port))
1282+
}
12711283

1272-
use super::{load_from_str, Format, Resource};
1284+
fn unspecified() -> impl Strategy<Value = IpAddr> {
1285+
prop_oneof![
1286+
Just(Ipv4Addr::UNSPECIFIED.into()),
1287+
Just(Ipv6Addr::UNSPECIFIED.into()),
1288+
]
1289+
}
1290+
1291+
fn specaddr() -> impl Strategy<Value = IpAddr> {
1292+
any::<IpAddr>().prop_filter("Must be specific address", |addr| !addr.is_unspecified())
1293+
}
12731294

1274-
fn localhost(port: u16) -> Resource {
1275-
Resource::tcp(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), port))
1295+
fn specport() -> impl Strategy<Value = u16> {
1296+
any::<u16>().prop_filter("Must be specific port", |&port| port > 0)
12761297
}
12771298

12781299
fn hashmap(conflicts: Vec<(Resource, Vec<&str>)>) -> HashMap<Resource, HashSet<&str>> {
@@ -1282,104 +1303,98 @@ mod resource_tests {
12821303
.collect()
12831304
}
12841305

1285-
#[test]
1286-
fn valid() {
1287-
let components = vec![
1288-
("sink_0", vec![localhost(0)]),
1289-
("sink_1", vec![localhost(1)]),
1290-
("sink_2", vec![localhost(2)]),
1291-
];
1292-
let conflicting = Resource::conflicts(components);
1293-
assert_eq!(conflicting, HashMap::new());
1294-
}
1306+
proptest! {
1307+
#[test]
1308+
fn valid(addr: IpAddr, port1 in specport(), port2 in specport()) {
1309+
let components = vec![
1310+
("sink_0", vec![tcp(addr, 0)]),
1311+
("sink_1", vec![tcp(addr, port1)]),
1312+
("sink_2", vec![tcp(addr, port2)]),
1313+
];
1314+
let conflicting = Resource::conflicts(components);
1315+
assert_eq!(conflicting, HashMap::new());
1316+
}
12951317

1296-
#[test]
1297-
fn conflicting_pair() {
1298-
let components = vec![
1299-
("sink_0", vec![localhost(0)]),
1300-
("sink_1", vec![localhost(2)]),
1301-
("sink_2", vec![localhost(2)]),
1302-
];
1303-
let conflicting = Resource::conflicts(components);
1304-
assert_eq!(
1305-
conflicting,
1306-
hashmap(vec![(localhost(2), vec!["sink_1", "sink_2"])])
1307-
);
1308-
}
1318+
#[test]
1319+
fn conflicting_pair(addr: IpAddr, port in specport()) {
1320+
let components = vec![
1321+
("sink_0", vec![tcp(addr, 0)]),
1322+
("sink_1", vec![tcp(addr, port)]),
1323+
("sink_2", vec![tcp(addr, port)]),
1324+
];
1325+
let conflicting = Resource::conflicts(components);
1326+
assert_eq!(
1327+
conflicting,
1328+
hashmap(vec![(tcp(addr, port), vec!["sink_1", "sink_2"])])
1329+
);
1330+
}
13091331

1310-
#[test]
1311-
fn conflicting_multi() {
1312-
let components = vec![
1313-
("sink_0", vec![localhost(0)]),
1314-
("sink_1", vec![localhost(2), localhost(0)]),
1315-
("sink_2", vec![localhost(2)]),
1316-
];
1317-
let conflicting = Resource::conflicts(components);
1318-
assert_eq!(
1319-
conflicting,
1320-
hashmap(vec![
1321-
(localhost(0), vec!["sink_0", "sink_1"]),
1322-
(localhost(2), vec!["sink_1", "sink_2"])
1323-
])
1324-
);
1325-
}
1332+
#[test]
1333+
fn conflicting_multi(addr: IpAddr, port in specport()) {
1334+
let components = vec![
1335+
("sink_0", vec![tcp(addr, 0)]),
1336+
("sink_1", vec![tcp(addr, port), tcp(addr, 0)]),
1337+
("sink_2", vec![tcp(addr, port)]),
1338+
];
1339+
let conflicting = Resource::conflicts(components);
1340+
assert_eq!(
1341+
conflicting,
1342+
hashmap(vec![
1343+
(tcp(addr, 0), vec!["sink_0", "sink_1"]),
1344+
(tcp(addr, port), vec!["sink_1", "sink_2"])
1345+
])
1346+
);
1347+
}
13261348

1327-
#[test]
1328-
fn different_network_interface() {
1329-
let components = vec![
1330-
("sink_0", vec![localhost(0)]),
1331-
(
1332-
"sink_1",
1333-
vec![Resource::tcp(SocketAddr::new(
1334-
Ipv4Addr::new(127, 0, 0, 2).into(),
1335-
0,
1336-
))],
1337-
),
1338-
];
1339-
let conflicting = Resource::conflicts(components);
1340-
assert_eq!(conflicting, HashMap::new());
1341-
}
1349+
#[test]
1350+
fn different_network_interface(addr1: IpAddr, addr2: IpAddr, port: u16) {
1351+
prop_assume!(addr1 != addr2);
1352+
let components = vec![
1353+
("sink_0", vec![tcp(addr1, port)]),
1354+
("sink_1", vec![tcp(addr2, port)]),
1355+
];
1356+
let conflicting = Resource::conflicts(components);
1357+
assert_eq!(conflicting, HashMap::new());
1358+
}
13421359

1343-
#[test]
1344-
fn unspecified_network_interface() {
1345-
let components = vec![
1346-
("sink_0", vec![localhost(0)]),
1347-
(
1348-
"sink_1",
1349-
vec![Resource::tcp(SocketAddr::new(
1350-
Ipv4Addr::UNSPECIFIED.into(),
1351-
0,
1352-
))],
1353-
),
1354-
];
1355-
let conflicting = Resource::conflicts(components);
1356-
assert_eq!(
1357-
conflicting,
1358-
hashmap(vec![(localhost(0), vec!["sink_0", "sink_1"])])
1359-
);
1360+
#[test]
1361+
fn unspecified_network_interface(addr in specaddr(), unspec in unspecified(), port: u16) {
1362+
let components = vec![
1363+
("sink_0", vec![tcp(addr, port)]),
1364+
("sink_1", vec![tcp(unspec, port)]),
1365+
];
1366+
let conflicting = Resource::conflicts(components);
1367+
assert_eq!(conflicting, HashMap::new());
1368+
}
1369+
1370+
#[test]
1371+
fn different_protocol(addr: IpAddr) {
1372+
let components = vec![
1373+
("sink_0", vec![tcp(addr, 0)]),
1374+
("sink_1", vec![udp(addr, 0)]),
1375+
];
1376+
let conflicting = Resource::conflicts(components);
1377+
assert_eq!(conflicting, HashMap::new());
1378+
}
13601379
}
13611380

13621381
#[test]
1363-
fn different_protocol() {
1382+
fn different_unspecified_ip_version() {
13641383
let components = vec![
1365-
(
1366-
"sink_0",
1367-
vec![Resource::tcp(SocketAddr::new(
1368-
Ipv4Addr::LOCALHOST.into(),
1369-
0,
1370-
))],
1371-
),
1372-
(
1373-
"sink_1",
1374-
vec![Resource::udp(SocketAddr::new(
1375-
Ipv4Addr::LOCALHOST.into(),
1376-
0,
1377-
))],
1378-
),
1384+
("sink_0", vec![tcp(Ipv4Addr::UNSPECIFIED, 0)]),
1385+
("sink_1", vec![tcp(Ipv6Addr::UNSPECIFIED, 0)]),
13791386
];
13801387
let conflicting = Resource::conflicts(components);
13811388
assert_eq!(conflicting, HashMap::new());
13821389
}
1390+
}
1391+
1392+
#[cfg(all(test, feature = "sources-stdin", feature = "sinks-console"))]
1393+
mod resource_config_tests {
1394+
use indoc::indoc;
1395+
use vector_config::schema::generate_root_schema;
1396+
1397+
use super::{load_from_str, Format};
13831398

13841399
#[test]
13851400
fn config_conflict_detected() {

0 commit comments

Comments
 (0)