Skip to content

Commit

Permalink
Fix RangeSet::filter() used by Redundant multipath scheduler (#253)
Browse files Browse the repository at this point in the history
- Update test scripts for multipath
- Update unit test for RangeSet:filter
  • Loading branch information
iyangsj authored Apr 30, 2024
1 parent 662f3ca commit 67c3331
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 16 deletions.
53 changes: 50 additions & 3 deletions src/ranges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use std::ops::Range;

use std::collections::btree_map;
use std::collections::BTreeMap;
use std::collections::Bound::Excluded;
use std::collections::Bound::Included;
use std::collections::Bound::Unbounded;

Expand Down Expand Up @@ -170,7 +171,7 @@ impl RangeSet {
}
}

if let Some(r) = self.next_to(range.start) {
if let Some(r) = self.next_after(range.start) {
if r.start < range.end {
new_end = r.start
}
Expand Down Expand Up @@ -216,22 +217,30 @@ impl RangeSet {
}
}

/// Find the closest range to `elem` that begins at or before it.
/// Find the closest range to `elem` that begins *at* or before it.
fn prev_to(&self, elem: u64) -> Option<Range<u64>> {
self.set
.range((Unbounded, Included(elem)))
.map(|(&s, &e)| (s..e))
.next_back()
}

/// Find the closest range to `elem` that begins after it.
/// Find the closest range to `elem` that begins *at* or after it.
fn next_to(&self, elem: u64) -> Option<Range<u64>> {
self.set
.range((Included(elem), Unbounded))
.map(|(&s, &e)| (s..e))
.next()
}

/// Find the closest range to `elem` that begins after it.
fn next_after(&self, elem: u64) -> Option<Range<u64>> {
self.set
.range((Excluded(elem), Unbounded))
.map(|(&s, &e)| (s..e))
.next()
}

/// Check if the element exists or not
pub fn contains(&self, elem: u64) -> bool {
if let Some(prev) = self.prev_to(elem) {
Expand Down Expand Up @@ -810,17 +819,29 @@ mod tests {

#[test]
fn filter() {
// simple cases
let cases = [
(vec![2..4, 6..8], 0..2, Some(0..2)),
(vec![2..4, 6..8], 4..6, Some(4..6)),
(vec![2..4, 6..8], 8..9, Some(8..9)),
(vec![], 8..9, Some(8..9)),
(vec![2..4, 6..8], 2..4, None),
(vec![2..4, 6..8], 6..8, None),
(vec![2..4, 6..8], 2..3, None),
(vec![2..4, 6..8], 3..4, None),
(vec![2..4, 6..8], 6..7, None),
(vec![2..4, 6..8], 7..8, None),
(vec![2..4, 6..8], 0..4, Some(0..2)),
(vec![2..4, 6..8], 2..5, Some(4..5)),
(vec![2..4, 6..8], 5..8, Some(5..6)),
(vec![2..4, 6..8], 6..9, Some(8..9)),
(vec![2..4, 6..8], 3..5, Some(4..5)),
(vec![2..4, 6..8], 7..9, Some(8..9)),
(vec![2..4, 6..8], 0..3, Some(0..2)),
(vec![2..4, 6..8], 5..7, Some(5..6)),
(vec![2..4, 6..8], 0..5, Some(0..2)),
(vec![2..4, 6..8], 5..9, Some(5..6)),
(vec![2..4, 6..8], 3..7, Some(4..6)),
(vec![2..4, 6..8], 3..9, Some(4..6)),
(vec![2..4, 6..8], 0..7, Some(0..2)),
(vec![2..4, 6..8], 0..9, Some(0..2)),
Expand All @@ -832,6 +853,32 @@ mod tests {
}
assert_eq!(rs.filter(case.1), case.2);
}

// all cases
let mut rs = RangeSet::default();
for r in vec![2..4, 6..8] {
rs.insert(r);
}
for i in 0..10 {
for j in i + 1..11 {
let res = rs.filter(i..j);
if (i < 2 && j <= 2) || (i >= 4 && j <= 6) || i >= 8 {
assert_eq!(res, Some(i..j), "{:?} want {:?}, got {:?}", i..j, i..j, res)
} else if i < 2 && j > 2 {
assert_eq!(res, Some(i..2), "{:?} want {:?}, got {:?}", i..j, i..2, res)
} else if i >= 2 && i <= 4 && j > 4 && j <= 6 {
assert_eq!(res, Some(4..j), "{:?} want {:?}, got {:?}", i..j, 4..j, res)
} else if i >= 2 && i <= 4 && j > 4 && j > 6 {
assert_eq!(res, Some(4..6), "{:?} want {:?}, got {:?}", i..j, 4..6, res)
} else if i >= 4 && i < 6 && j >= 6 {
assert_eq!(res, Some(i..6), "{:?} want {:?}, got {:?}", i..j, i..6, res)
} else if i >= 6 && i < 8 && j > 8 {
assert_eq!(res, Some(8..j), "{:?} want {:?}, got {:?}", i..j, 8..j, res)
} else {
assert_eq!(res, None, "{:?} want None, got {:?}", i..j, res)
}
}
}
}

#[test]
Expand Down
52 changes: 39 additions & 13 deletions tools/tests/tquic_tools_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,25 @@ set -e
BIN_DIR="./"
TEST_DIR="./test-`date +%Y%m%d%H%M%S`"
TEST_CASES="multipath_minrtt,multipath_roundrobin,multipath_redundant"
TEST_PID="$$"
TEST_FILE="10M"
PATH_NUM=4

# Ensure that all child processes have exited.
trap 'pkill -P $TEST_PID' EXIT

show_help() {
echo "Usage: $0 [options]"
echo " -b, Set the directory of tquic_client/tquic_server."
echo " -w, Set the workring directory for testing."
echo " -l, List all supported test cases."
echo " -t, Run the specified test cases."
echo " -f, File size for test cases, eg. 10M"
echo " -p, Path number for test cases, eg. 4"
echo " -h, Display this help and exit."
}

while getopts ":b:w:t:lh" opt; do
while getopts ":b:w:t:f:p:lh" opt; do
case $opt in
b)
BIN_DIR="$OPTARG"
Expand All @@ -44,6 +52,12 @@ while getopts ":b:w:t:lh" opt; do
t)
TEST_CASES="$OPTARG"
;;
f)
TEST_FILE="$OPTARG"
;;
p)
PATH_NUM="$OPTARG"
;;
l)
echo $TEST_CASES
exit 0
Expand All @@ -64,6 +78,14 @@ while getopts ":b:w:t:lh" opt; do
esac
done

if [[ ! -f "$BIN_DIR/tquic_client" || ! -f "$BIN_DIR/tquic_server" ]]; then
echo "Not found tquic_client/tquic_server. Please specify the directory for them by '-b' option."
show_help
exit
fi

CID_LIMIT=$(( $PATH_NUM * 2 ))

generate_cert() {
local cert_dir="$1/cert"
mkdir -p $cert_dir
Expand All @@ -75,8 +97,7 @@ generate_cert() {
generate_files() {
local data_dir="$1/data"
mkdir -p $data_dir
dd if=/dev/urandom of=$data_dir/1m bs=1M count=1
dd if=/dev/urandom of=$data_dir/10m bs=1M count=10
dd if=/dev/urandom of=$data_dir/$TEST_FILE bs=$TEST_FILE count=1
}

test_multipath() {
Expand All @@ -94,28 +115,33 @@ test_multipath() {
generate_files $test_dir

# start tquic server
$BIN_DIR/tquic_server -l 127.0.8.8:8443 --enable-multipath --multipath-algor $algor \
--cert $cert_dir/cert.crt --key $cert_dir/cert.key \
--root $data_dir --active-cid-limit 8 &
RUST_BACKTRACE=1 $BIN_DIR/tquic_server -l 127.0.8.8:8443 --enable-multipath --multipath-algor $algor \
--cert $cert_dir/cert.crt --key $cert_dir/cert.key --root $data_dir \
--active-cid-limit $CID_LIMIT --log-file $test_dir/server.log --log-level debug &
server_pid=$!
trap "kill $server_pid" RETURN

# start tquic client
mkdir -p $dump_dir
$BIN_DIR/tquic_client -c 127.0.8.8:8443 --enable-multipath --multipath-algor $algor \
--local-addresses 127.0.0.1,127.0.0.2,127.0.0.3,127.0.0.4 --active-cid-limit 8 \
local_addresses=`seq -s, -f "127.0.0.%g" 1 $PATH_NUM`
RUST_BACKTRACE=1 $BIN_DIR/tquic_client -c 127.0.8.8:8443 --enable-multipath --multipath-algor $algor \
--local-addresses $local_addresses --active-cid-limit $CID_LIMIT \
--qlog-dir $qlog_dir --log-file $test_dir/client.log --log-level trace \
--dump-dir $dump_dir \
https://example.org/10m
https://example.org/$TEST_FILE

# check files
if ! cmp -s $dump_dir/10m $data_dir/10m; then
echo "Files not same $dump_dir/1m:$data_dir/1m"
if ! cmp -s $dump_dir/$TEST_FILE $data_dir/$TEST_FILE; then
echo "Files not same $dump_dir/$TEST_FILE:$data_dir/$TEST_FILE"
exit 1
fi

# check logs
grep "recv packet OneRTT" $test_dir/client.log | grep "local=.*" -o | sort | uniq -c
# check packets received
pnum=`grep "recv packet OneRTT" $test_dir/client.log | grep "local=.*" -o | sort | uniq -c | tee /dev/stderr | wc -l`
if [ $pnum != $PATH_NUM ]; then
echo "Not all path ($pnum/$PATH_NUM) received packets"
exit 1
fi

echo "Test $algor OK"
}
Expand Down

0 comments on commit 67c3331

Please sign in to comment.