Metainfo refactoring
- Combine test Metainfo values into a small number of globally available values. - Serialize update URLs as `URL` insted of `String`. - Add additional `show` tests type: reform
This commit is contained in:
parent
f4f7a69069
commit
213624cf8e
|
@ -39,7 +39,6 @@ strum_macros = "0.18.0"
|
|||
syn = "1.0.14"
|
||||
tempfile = "3.0.0"
|
||||
unicode-width = "0.1.0"
|
||||
url = "2.1.1"
|
||||
|
||||
[dependencies.bendy]
|
||||
version = "0.3.0"
|
||||
|
@ -57,6 +56,10 @@ features = ["derive"]
|
|||
version = "0.3.0"
|
||||
features = ["default", "wrap_help"]
|
||||
|
||||
[dependencies.url]
|
||||
version = "2.1.1"
|
||||
features = ["serde"]
|
||||
|
||||
[dev-dependencies]
|
||||
claim = "0.3.1"
|
||||
temptree = "0.0.0"
|
||||
|
|
|
@ -26,7 +26,7 @@ pub(crate) struct Info {
|
|||
with = "unwrap_or_skip",
|
||||
rename = "update-url"
|
||||
)]
|
||||
pub(crate) update_url: Option<String>,
|
||||
pub(crate) update_url: Option<Url>,
|
||||
}
|
||||
|
||||
impl Info {
|
||||
|
|
520
src/metainfo.rs
520
src/metainfo.rs
|
@ -117,155 +117,69 @@ impl Metainfo {
|
|||
pub(crate) fn infohash(&self) -> Result<Infohash> {
|
||||
self.info.infohash()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn round_trip_single() {
|
||||
let value = Metainfo {
|
||||
announce: Some("announce".into()),
|
||||
announce_list: Some(vec![vec!["announce".into(), "b".into()], vec!["c".into()]]),
|
||||
comment: Some("comment".into()),
|
||||
created_by: Some("created by".into()),
|
||||
creation_date: Some(1),
|
||||
encoding: Some("UTF-8".into()),
|
||||
nodes: Some(vec!["x:12".parse().unwrap(), "1.1.1.1:16".parse().unwrap()]),
|
||||
info: Info {
|
||||
private: Some(true),
|
||||
piece_length: Bytes(16 * 1024),
|
||||
source: Some("source".into()),
|
||||
name: "foo".into(),
|
||||
pieces: PieceList::from_pieces(&["abc"]),
|
||||
mode: Mode::Single {
|
||||
length: Bytes(20),
|
||||
md5sum: None,
|
||||
},
|
||||
update_url: None,
|
||||
},
|
||||
};
|
||||
|
||||
let bencode = bendy::serde::ser::to_bytes(&value).unwrap();
|
||||
|
||||
let deserialized = bendy::serde::de::from_bytes(&bencode).unwrap();
|
||||
|
||||
assert_eq!(value, deserialized);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trip_multiple() {
|
||||
let value = Metainfo {
|
||||
announce: Some("announce".into()),
|
||||
announce_list: Some(vec![vec!["announce".into(), "b".into()], vec!["c".into()]]),
|
||||
nodes: Some(vec!["x:12".parse().unwrap(), "1.1.1.1:16".parse().unwrap()]),
|
||||
comment: Some("comment".into()),
|
||||
created_by: Some("created by".into()),
|
||||
creation_date: Some(1),
|
||||
encoding: Some("UTF-8".into()),
|
||||
info: Info {
|
||||
private: Some(true),
|
||||
piece_length: Bytes(16 * 1024),
|
||||
source: Some("source".into()),
|
||||
name: "foo".into(),
|
||||
pieces: PieceList::from_pieces(&["abc"]),
|
||||
mode: Mode::Multiple {
|
||||
files: vec![FileInfo {
|
||||
length: Bytes(10),
|
||||
path: FilePath::from_components(&["foo", "bar"]),
|
||||
md5sum: Some(Md5Digest::from_hex("000102030405060708090a0b0c0d0e0f")),
|
||||
}],
|
||||
},
|
||||
update_url: None,
|
||||
},
|
||||
};
|
||||
|
||||
let bencode = bendy::serde::ser::to_bytes(&value).unwrap();
|
||||
|
||||
let deserialized = bendy::serde::de::from_bytes(&bencode).unwrap();
|
||||
|
||||
assert_eq!(value, deserialized);
|
||||
}
|
||||
|
||||
fn representation(value: Metainfo, want: &str) {
|
||||
let have = value.serialize().unwrap();
|
||||
|
||||
if have != want.as_bytes() {
|
||||
eprintln!("have:");
|
||||
eprintln!("{}", String::from_utf8_lossy(&have));
|
||||
eprintln!("want:");
|
||||
eprintln!("{}", want);
|
||||
panic!("Unexpected representation...");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bencode_representation_single_some() {
|
||||
let value = Metainfo {
|
||||
announce: Some("ANNOUNCE".into()),
|
||||
announce_list: Some(vec![vec!["A".into(), "B".into()], vec!["C".into()]]),
|
||||
#[cfg(test)]
|
||||
pub(crate) fn test_value_single() -> Metainfo {
|
||||
Metainfo {
|
||||
announce: Some("udp://announce.example:1337".into()),
|
||||
announce_list: Some(vec![
|
||||
vec![
|
||||
"http://a.example:4567".into(),
|
||||
"https://b.example:77".into(),
|
||||
],
|
||||
vec!["udp://c.example:88".into()],
|
||||
]),
|
||||
nodes: Some(vec![
|
||||
"domain:1".parse().unwrap(),
|
||||
"node.example:12".parse().unwrap(),
|
||||
"1.1.1.1:16".parse().unwrap(),
|
||||
"[1234:5678:9abc:def0:1234:5678:9abc:def0]:65000"
|
||||
.parse()
|
||||
.unwrap(),
|
||||
"[2001:0db8:85a3::0000:8a2e:0370]:7334".parse().unwrap(),
|
||||
]),
|
||||
comment: Some("COMMENT".into()),
|
||||
created_by: Some("CREATED BY".into()),
|
||||
creation_date: Some(0),
|
||||
creation_date: Some(1),
|
||||
encoding: Some("UTF-8".into()),
|
||||
info: Info {
|
||||
private: Some(true),
|
||||
piece_length: Bytes(1024),
|
||||
piece_length: Bytes(16 * 1024),
|
||||
source: Some("SOURCE".into()),
|
||||
name: "NAME".into(),
|
||||
pieces: PieceList::from_pieces(&["fae50"]),
|
||||
pieces: PieceList::from_pieces(&["fae50", "fae50"]),
|
||||
mode: Mode::Single {
|
||||
length: Bytes(5),
|
||||
length: Bytes(32 * 1024),
|
||||
md5sum: Some(Md5Digest::from_hex("000102030405060708090a0b0c0d0e0f")),
|
||||
},
|
||||
update_url: None,
|
||||
update_url: Some("https://update.example".parse().unwrap()),
|
||||
},
|
||||
};
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = concat!(
|
||||
"d",
|
||||
"8:announce", "8:ANNOUNCE",
|
||||
"13:announce-list", "l",
|
||||
"l", "1:A", "1:B", "e",
|
||||
"l", "1:C", "e",
|
||||
"e",
|
||||
"7:comment", "7:COMMENT",
|
||||
"10:created by", "10:CREATED BY",
|
||||
"13:creation date", "i0e",
|
||||
"8:encoding", "5:UTF-8",
|
||||
"4:info", "d",
|
||||
"6:length", "i5e",
|
||||
"6:md5sum", "32:000102030405060708090a0b0c0d0e0f",
|
||||
"4:name", "4:NAME",
|
||||
"12:piece length", "i1024e",
|
||||
"6:pieces", "20:8,OS7d玤{Qk!Mk",
|
||||
"7:private", "i1e",
|
||||
"6:source", "6:SOURCE",
|
||||
"e",
|
||||
"5:nodes", "l",
|
||||
"l", "6:domain", "i1e", "e",
|
||||
"l", "7:1.1.1.1", "i16e", "e",
|
||||
"l", "39:1234:5678:9abc:def0:1234:5678:9abc:def0", "i65000e", "e",
|
||||
"e",
|
||||
"e"
|
||||
);
|
||||
|
||||
representation(value, want);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bencode_representation_single_none() {
|
||||
let value = Metainfo {
|
||||
announce: Some("ANNOUNCE".into()),
|
||||
#[cfg(test)]
|
||||
pub(crate) fn test_value_single_infohash() -> &'static str {
|
||||
"5d6f53772b4c20536fcce0c4c364d764a6efa39c"
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn test_value_single_torrent_size() -> Bytes {
|
||||
Bytes(509)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn test_value_multiple() -> Metainfo {
|
||||
let mut instance = Self::test_value_single();
|
||||
instance.info.mode = Mode::Multiple {
|
||||
files: vec![FileInfo {
|
||||
length: Bytes(32 * 1024),
|
||||
path: FilePath::from_components(&["DIR", "FILE"]),
|
||||
md5sum: Some(Md5Digest::from_hex("000102030405060708090a0b0c0d0e0f")),
|
||||
}],
|
||||
};
|
||||
instance
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn test_value_single_unset() -> Metainfo {
|
||||
Metainfo {
|
||||
announce: None,
|
||||
announce_list: None,
|
||||
nodes: None,
|
||||
comment: None,
|
||||
|
@ -284,77 +198,23 @@ mod tests {
|
|||
},
|
||||
update_url: None,
|
||||
},
|
||||
};
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = concat!(
|
||||
"d",
|
||||
"8:announce", "8:ANNOUNCE",
|
||||
"4:info", "d",
|
||||
"6:length", "i5e",
|
||||
"4:name", "4:NAME",
|
||||
"12:piece length", "i1024e",
|
||||
"6:pieces", "20:8,OS7d玤{Qk!Mk",
|
||||
"e",
|
||||
"e"
|
||||
);
|
||||
|
||||
representation(value, want);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bencode_representation_multiple_some() {
|
||||
let value = Metainfo {
|
||||
announce: Some("ANNOUNCE".into()),
|
||||
announce_list: None,
|
||||
nodes: None,
|
||||
comment: None,
|
||||
created_by: None,
|
||||
creation_date: None,
|
||||
encoding: None,
|
||||
info: Info {
|
||||
private: None,
|
||||
piece_length: Bytes(1024),
|
||||
source: None,
|
||||
name: "NAME".into(),
|
||||
pieces: PieceList::from_pieces(&["fae50"]),
|
||||
mode: Mode::Multiple {
|
||||
files: vec![FileInfo {
|
||||
length: Bytes(1024),
|
||||
md5sum: Some(Md5Digest::from_hex("000102030405060708090a0b0c0d0e0f")),
|
||||
path: FilePath::from_components(&["a", "b"]),
|
||||
}],
|
||||
},
|
||||
update_url: None,
|
||||
},
|
||||
};
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = concat!(
|
||||
"d",
|
||||
"8:announce", "8:ANNOUNCE",
|
||||
"4:info", "d",
|
||||
"5:files", "l",
|
||||
"d",
|
||||
"6:length", "i1024e",
|
||||
"6:md5sum", "32:000102030405060708090a0b0c0d0e0f",
|
||||
"4:path", "l", "1:a", "1:b", "e",
|
||||
"e",
|
||||
"e",
|
||||
"4:name", "4:NAME",
|
||||
"12:piece length", "i1024e",
|
||||
"6:pieces", "20:8,OS7d玤{Qk!Mk",
|
||||
"e",
|
||||
"e"
|
||||
);
|
||||
|
||||
representation(value, want);
|
||||
#[cfg(test)]
|
||||
pub(crate) fn test_value_single_unset_infohash() -> &'static str {
|
||||
"a9105b0ff5f7cefeee5599ed7831749be21cc04e"
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bencode_representation_multiple_none() {
|
||||
let value = Metainfo {
|
||||
announce: Some("ANNOUNCE".into()),
|
||||
#[cfg(test)]
|
||||
pub(crate) fn test_value_single_unset_torrent_size() -> Bytes {
|
||||
Bytes(85)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn test_value_multiple_unset() -> Metainfo {
|
||||
Metainfo {
|
||||
announce: None,
|
||||
announce_list: None,
|
||||
nodes: None,
|
||||
comment: None,
|
||||
|
@ -376,12 +236,167 @@ mod tests {
|
|||
},
|
||||
update_url: None,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn round_trip_single() {
|
||||
let value = Metainfo::test_value_single();
|
||||
|
||||
let bencode = bendy::serde::ser::to_bytes(&value).unwrap();
|
||||
|
||||
let deserialized = bendy::serde::de::from_bytes(&bencode).unwrap();
|
||||
|
||||
assert_eq!(value, deserialized);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trip_multiple() {
|
||||
let value = Metainfo::test_value_multiple();
|
||||
|
||||
let bencode = bendy::serde::ser::to_bytes(&value).unwrap();
|
||||
|
||||
let deserialized = bendy::serde::de::from_bytes(&bencode).unwrap();
|
||||
|
||||
assert_eq!(value, deserialized);
|
||||
}
|
||||
|
||||
fn representation(value: Metainfo, want: &str) {
|
||||
let have = value.serialize().unwrap();
|
||||
|
||||
if have != want.as_bytes() {
|
||||
let have = String::from_utf8_lossy(&have);
|
||||
assert_eq!(have, want);
|
||||
eprintln!("have:");
|
||||
eprintln!("{}", have);
|
||||
eprintln!("want:");
|
||||
eprintln!("{}", want);
|
||||
panic!("Unexpected representation...");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bencode_representation_single_set() {
|
||||
let value = Metainfo::test_value_single();
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = concat!(
|
||||
"d",
|
||||
"8:announce", "27:udp://announce.example:1337",
|
||||
"13:announce-list", "l",
|
||||
"l",
|
||||
"21:http://a.example:4567",
|
||||
"20:https://b.example:77",
|
||||
"e",
|
||||
"l",
|
||||
"18:udp://c.example:88",
|
||||
"e",
|
||||
"e",
|
||||
"7:comment", "7:COMMENT",
|
||||
"10:created by", "10:CREATED BY",
|
||||
"13:creation date", "i1e",
|
||||
"8:encoding", "5:UTF-8",
|
||||
"4:info", "d",
|
||||
"6:length", "i32768e",
|
||||
"6:md5sum", "32:000102030405060708090a0b0c0d0e0f",
|
||||
"4:name", "4:NAME",
|
||||
"12:piece length", "i16384e",
|
||||
"6:pieces", "40:8,OS7d玤{Qk!Mk8,OS7d玤{Qk!Mk",
|
||||
"7:private", "i1e",
|
||||
"6:source", "6:SOURCE",
|
||||
"10:update-url", "23:https://update.example/",
|
||||
"e",
|
||||
"5:nodes", "l",
|
||||
"l", "12:node.example", "i12e", "e",
|
||||
"l", "7:1.1.1.1", "i16e", "e",
|
||||
"l", "23:2001:db8:85a3::8a2e:370", "i7334e", "e",
|
||||
"e",
|
||||
"e"
|
||||
);
|
||||
|
||||
representation(value, want);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bencode_representation_single_unset() {
|
||||
let value = Metainfo::test_value_single_unset();
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = concat!(
|
||||
"d",
|
||||
"4:info", "d",
|
||||
"6:length", "i5e",
|
||||
"4:name", "4:NAME",
|
||||
"12:piece length", "i1024e",
|
||||
"6:pieces", "20:8,OS7d玤{Qk!Mk",
|
||||
"e",
|
||||
"e"
|
||||
);
|
||||
|
||||
representation(value, want);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bencode_representation_multiple_set() {
|
||||
let value = Metainfo::test_value_multiple();
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = concat!(
|
||||
"d",
|
||||
"8:announce", "27:udp://announce.example:1337",
|
||||
"13:announce-list", "l",
|
||||
"l",
|
||||
"21:http://a.example:4567",
|
||||
"20:https://b.example:77",
|
||||
"e",
|
||||
"l",
|
||||
"18:udp://c.example:88",
|
||||
"e",
|
||||
"e",
|
||||
"7:comment", "7:COMMENT",
|
||||
"10:created by", "10:CREATED BY",
|
||||
"13:creation date", "i1e",
|
||||
"8:encoding", "5:UTF-8",
|
||||
"4:info", "d",
|
||||
"5:files", "l",
|
||||
"d",
|
||||
"6:length", "i32768e",
|
||||
"6:md5sum", "32:000102030405060708090a0b0c0d0e0f",
|
||||
"4:path", "l", "3:DIR", "4:FILE", "e",
|
||||
"e",
|
||||
"e",
|
||||
"4:name", "4:NAME",
|
||||
"12:piece length", "i16384e",
|
||||
"6:pieces", "40:8,OS7d玤{Qk!Mk8,OS7d玤{Qk!Mk",
|
||||
"7:private", "i1e",
|
||||
"6:source", "6:SOURCE",
|
||||
"10:update-url", "23:https://update.example/",
|
||||
"e",
|
||||
"5:nodes", "l",
|
||||
"l", "12:node.example", "i12e", "e",
|
||||
"l", "7:1.1.1.1", "i16e", "e",
|
||||
"l", "23:2001:db8:85a3::8a2e:370", "i7334e", "e",
|
||||
"e",
|
||||
"e"
|
||||
);
|
||||
|
||||
representation(value, want);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bencode_representation_multiple_unset() {
|
||||
let value = Metainfo::test_value_multiple_unset();
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = concat!(
|
||||
"d",
|
||||
"8:announce", "8:ANNOUNCE",
|
||||
"4:info", "d",
|
||||
"5:files", "l",
|
||||
"d",
|
||||
|
@ -400,85 +415,44 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn private_false() {
|
||||
let value = Metainfo {
|
||||
announce: Some("ANNOUNCE".into()),
|
||||
announce_list: None,
|
||||
nodes: None,
|
||||
comment: None,
|
||||
created_by: None,
|
||||
creation_date: None,
|
||||
encoding: None,
|
||||
info: Info {
|
||||
private: Some(false),
|
||||
piece_length: Bytes(1024),
|
||||
source: None,
|
||||
name: "NAME".into(),
|
||||
pieces: PieceList::from_pieces(&["fae50"]),
|
||||
mode: Mode::Single {
|
||||
length: Bytes(5),
|
||||
md5sum: None,
|
||||
},
|
||||
update_url: None,
|
||||
},
|
||||
};
|
||||
fn trackers() {
|
||||
fn assert_trackers_eq(metainfo: &Metainfo, want: &[&str]) {
|
||||
let want = want
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(Url::parse)
|
||||
.collect::<Result<Vec<Url>, url::ParseError>>()
|
||||
.unwrap();
|
||||
let have = metainfo.trackers().collect::<Result<Vec<Url>>>().unwrap();
|
||||
assert_eq!(have, want);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = concat!(
|
||||
"d",
|
||||
"8:announce", "8:ANNOUNCE",
|
||||
"4:info", "d",
|
||||
"6:length", "i5e",
|
||||
"4:name", "4:NAME",
|
||||
"12:piece length", "i1024e",
|
||||
"6:pieces", "20:8,OS7d玤{Qk!Mk",
|
||||
"7:private", "i0e",
|
||||
"e",
|
||||
"e"
|
||||
let mut metainfo = Metainfo::test_value_single();
|
||||
|
||||
assert_trackers_eq(
|
||||
&metainfo,
|
||||
&[
|
||||
"udp://announce.example:1337",
|
||||
"http://a.example:4567",
|
||||
"https://b.example:77",
|
||||
"udp://c.example:88",
|
||||
],
|
||||
);
|
||||
|
||||
representation(value, want);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trackers() {
|
||||
let mut metainfo = Metainfo {
|
||||
announce: Some("http://foo".into()),
|
||||
announce_list: None,
|
||||
nodes: None,
|
||||
comment: None,
|
||||
created_by: None,
|
||||
creation_date: None,
|
||||
encoding: None,
|
||||
info: Info {
|
||||
private: Some(false),
|
||||
piece_length: Bytes(1024),
|
||||
source: None,
|
||||
name: "NAME".into(),
|
||||
pieces: PieceList::from_pieces(&["fae50"]),
|
||||
mode: Mode::Single {
|
||||
length: Bytes(5),
|
||||
md5sum: None,
|
||||
},
|
||||
update_url: None,
|
||||
},
|
||||
};
|
||||
|
||||
let trackers = metainfo.trackers().collect::<Result<Vec<Url>>>().unwrap();
|
||||
assert_eq!(trackers, &["http://foo".parse().unwrap()]);
|
||||
|
||||
metainfo.announce_list = Some(vec![
|
||||
vec!["http://bar".into(), "http://baz".into()],
|
||||
vec!["http://foo".into()],
|
||||
vec![
|
||||
"udp://announce.example:1337".into(),
|
||||
"https://b.example:77".into(),
|
||||
],
|
||||
vec!["udp://c.example:88".into()],
|
||||
]);
|
||||
|
||||
let trackers = metainfo.trackers().collect::<Result<Vec<Url>>>().unwrap();
|
||||
assert_eq!(
|
||||
trackers,
|
||||
assert_trackers_eq(
|
||||
&metainfo,
|
||||
&[
|
||||
"http://foo".parse().unwrap(),
|
||||
"http://bar".parse().unwrap(),
|
||||
"http://baz".parse().unwrap(),
|
||||
"udp://announce.example:1337",
|
||||
"https://b.example:77",
|
||||
"udp://c.example:88",
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -382,13 +382,13 @@ impl Create {
|
|||
}
|
||||
|
||||
let info = Info {
|
||||
source: self.source,
|
||||
piece_length: content.piece_length,
|
||||
name: content.name,
|
||||
piece_length: content.piece_length,
|
||||
source: self.source,
|
||||
update_url: self.update_url,
|
||||
mode,
|
||||
pieces,
|
||||
private,
|
||||
update_url: self.update_url.map(|url| url.to_string()),
|
||||
};
|
||||
|
||||
let metainfo = Metainfo {
|
||||
|
@ -3187,8 +3187,8 @@ Content Size 9 bytes
|
|||
env.assert_ok();
|
||||
let metainfo = env.load_metainfo("foo.torrent");
|
||||
assert_eq!(
|
||||
metainfo.info.update_url.as_deref(),
|
||||
Some("https://www.a_real_url.com/")
|
||||
metainfo.info.update_url,
|
||||
Some("https://www.a_real_url.com/".parse().unwrap())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,31 +111,53 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn output() -> Result<()> {
|
||||
let metainfo = Metainfo {
|
||||
announce: Some("announce".into()),
|
||||
announce_list: Some(vec![vec!["announce".into(), "b".into()], vec!["c".into()]]),
|
||||
nodes: Some(vec![
|
||||
"x:12".parse().unwrap(),
|
||||
"1.1.1.1:16".parse().unwrap(),
|
||||
"[2001:0db8:85a3::0000:8a2e:0370]:7334".parse().unwrap(),
|
||||
]),
|
||||
comment: Some("comment".into()),
|
||||
created_by: Some("created by".into()),
|
||||
creation_date: Some(1),
|
||||
encoding: Some("UTF-8".into()),
|
||||
info: Info {
|
||||
private: Some(true),
|
||||
piece_length: Bytes(16 * 1024),
|
||||
source: Some("source".into()),
|
||||
name: "foo".into(),
|
||||
pieces: PieceList::from_pieces(&["xyz", "abc"]),
|
||||
mode: Mode::Single {
|
||||
length: Bytes(20),
|
||||
md5sum: None,
|
||||
},
|
||||
update_url: None,
|
||||
},
|
||||
};
|
||||
let metainfo = Metainfo::test_value_single();
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want_human_readable = format!(
|
||||
" Name NAME
|
||||
Comment COMMENT
|
||||
Creation Date 1970-01-01 00:00:01 UTC
|
||||
Created By CREATED BY
|
||||
Source SOURCE
|
||||
Info Hash {}
|
||||
Torrent Size {}
|
||||
Content Size 32 KiB
|
||||
Private yes
|
||||
Tracker udp://announce.example:1337
|
||||
Announce List Tier 1: http://a.example:4567
|
||||
https://b.example:77
|
||||
Tier 2: udp://c.example:88
|
||||
Update URL https://update.example/
|
||||
DHT Nodes node.example:12
|
||||
1.1.1.1:16
|
||||
[2001:db8:85a3::8a2e:370]:7334
|
||||
Piece Size 16 KiB
|
||||
Piece Count 2
|
||||
File Count 1
|
||||
Files NAME
|
||||
", Metainfo::test_value_single_infohash(), Metainfo::test_value_single_torrent_size());
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want_machine_readable = format!("\
|
||||
name\tNAME
|
||||
comment\tCOMMENT
|
||||
creation date\t1970-01-01 00:00:01 UTC
|
||||
created by\tCREATED BY
|
||||
source\tSOURCE
|
||||
info hash\t{}
|
||||
torrent size\t{}
|
||||
content size\t32768
|
||||
private\tyes
|
||||
tracker\tudp://announce.example:1337
|
||||
announce list\thttp://a.example:4567\thttps://b.example:77\tudp://c.example:88
|
||||
update url\thttps://update.example/
|
||||
dht nodes\tnode.example:12\t1.1.1.1:16\t[2001:db8:85a3::8a2e:370]:7334
|
||||
piece size\t16384
|
||||
piece count\t2
|
||||
file count\t1
|
||||
files\tNAME
|
||||
", Metainfo::test_value_single_infohash(), Metainfo::test_value_single_torrent_size().count());
|
||||
|
||||
{
|
||||
let mut env = TestEnvBuilder::new()
|
||||
|
@ -150,29 +172,7 @@ mod tests {
|
|||
env.assert_ok();
|
||||
|
||||
let have = env.out();
|
||||
let want = " Name foo
|
||||
Comment comment
|
||||
Creation Date 1970-01-01 00:00:01 UTC
|
||||
Created By created by
|
||||
Source source
|
||||
Info Hash e12253978dc6d50db11d05747abcea1ad03b51c5
|
||||
Torrent Size 339 bytes
|
||||
Content Size 20 bytes
|
||||
Private yes
|
||||
Tracker announce
|
||||
Announce List Tier 1: announce
|
||||
b
|
||||
Tier 2: c
|
||||
DHT Nodes x:12
|
||||
1.1.1.1:16
|
||||
[2001:db8:85a3::8a2e:370]:7334
|
||||
Piece Size 16 KiB
|
||||
Piece Count 2
|
||||
File Count 1
|
||||
Files foo
|
||||
";
|
||||
|
||||
assert_eq!(have, want);
|
||||
assert_eq!(have, want_human_readable);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -188,29 +188,8 @@ Announce List Tier 1: announce
|
|||
env.assert_ok();
|
||||
|
||||
let have = env.out();
|
||||
let want = " Name foo
|
||||
Comment comment
|
||||
Creation Date 1970-01-01 00:00:01 UTC
|
||||
Created By created by
|
||||
Source source
|
||||
Info Hash e12253978dc6d50db11d05747abcea1ad03b51c5
|
||||
Torrent Size 339 bytes
|
||||
Content Size 20 bytes
|
||||
Private yes
|
||||
Tracker announce
|
||||
Announce List Tier 1: announce
|
||||
b
|
||||
Tier 2: c
|
||||
DHT Nodes x:12
|
||||
1.1.1.1:16
|
||||
[2001:db8:85a3::8a2e:370]:7334
|
||||
Piece Size 16 KiB
|
||||
Piece Count 2
|
||||
File Count 1
|
||||
Files foo
|
||||
";
|
||||
|
||||
assert_eq!(have, want);
|
||||
assert_eq!(have, want_human_readable);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -225,26 +204,8 @@ Announce List Tier 1: announce
|
|||
env.assert_ok();
|
||||
|
||||
let have = env.out();
|
||||
let want = "\
|
||||
name\tfoo
|
||||
comment\tcomment
|
||||
creation date\t1970-01-01 00:00:01 UTC
|
||||
created by\tcreated by
|
||||
source\tsource
|
||||
info hash\te12253978dc6d50db11d05747abcea1ad03b51c5
|
||||
torrent size\t339
|
||||
content size\t20
|
||||
private\tyes
|
||||
tracker\tannounce
|
||||
announce list\tannounce\tb\tc
|
||||
dht nodes\tx:12\t1.1.1.1:16\t[2001:db8:85a3::8a2e:370]:7334
|
||||
piece size\t16384
|
||||
piece count\t2
|
||||
file count\t1
|
||||
files\tfoo
|
||||
";
|
||||
|
||||
assert_eq!(have, want);
|
||||
assert_eq!(have, want_machine_readable);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -252,31 +213,7 @@ files\tfoo
|
|||
|
||||
#[test]
|
||||
fn tier_list_with_main() -> Result<()> {
|
||||
let metainfo = Metainfo {
|
||||
announce: Some("a".into()),
|
||||
announce_list: Some(vec![vec!["x".into()], vec!["y".into()], vec!["z".into()]]),
|
||||
comment: Some("comment".into()),
|
||||
created_by: Some("created by".into()),
|
||||
nodes: Some(vec![
|
||||
"x:12".parse().unwrap(),
|
||||
"1.1.1.1:16".parse().unwrap(),
|
||||
"[2001:0db8:85a3::0000:8a2e:0370]:7334".parse().unwrap(),
|
||||
]),
|
||||
creation_date: Some(1),
|
||||
encoding: Some("UTF-8".into()),
|
||||
info: Info {
|
||||
private: Some(true),
|
||||
piece_length: Bytes(16 * 1024),
|
||||
source: Some("source".into()),
|
||||
name: "foo".into(),
|
||||
pieces: PieceList::from_pieces(&["xyz", "abc"]),
|
||||
mode: Mode::Single {
|
||||
length: Bytes(20),
|
||||
md5sum: None,
|
||||
},
|
||||
update_url: None,
|
||||
},
|
||||
};
|
||||
let metainfo = Metainfo::test_value_single();
|
||||
|
||||
{
|
||||
let mut env = TestEnvBuilder::new()
|
||||
|
@ -291,27 +228,34 @@ files\tfoo
|
|||
env.assert_ok();
|
||||
|
||||
let have = env.out();
|
||||
let want = " Name foo
|
||||
Comment comment
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = format!(
|
||||
" Name NAME
|
||||
Comment COMMENT
|
||||
Creation Date 1970-01-01 00:00:01 UTC
|
||||
Created By created by
|
||||
Source source
|
||||
Info Hash e12253978dc6d50db11d05747abcea1ad03b51c5
|
||||
Torrent Size 327 bytes
|
||||
Content Size 20 bytes
|
||||
Created By CREATED BY
|
||||
Source SOURCE
|
||||
Info Hash {}
|
||||
Torrent Size {}
|
||||
Content Size 32 KiB
|
||||
Private yes
|
||||
Tracker a
|
||||
Announce List Tier 1: x
|
||||
Tier 2: y
|
||||
Tier 3: z
|
||||
DHT Nodes x:12
|
||||
Tracker udp://announce.example:1337
|
||||
Announce List Tier 1: http://a.example:4567
|
||||
https://b.example:77
|
||||
Tier 2: udp://c.example:88
|
||||
Update URL https://update.example/
|
||||
DHT Nodes node.example:12
|
||||
1.1.1.1:16
|
||||
[2001:db8:85a3::8a2e:370]:7334
|
||||
Piece Size 16 KiB
|
||||
Piece Count 2
|
||||
File Count 1
|
||||
Files foo
|
||||
";
|
||||
Files NAME
|
||||
",
|
||||
Metainfo::test_value_single_infohash(),
|
||||
Metainfo::test_value_single_torrent_size()
|
||||
);
|
||||
|
||||
assert_eq!(have, want);
|
||||
}
|
||||
|
@ -328,24 +272,31 @@ Announce List Tier 1: x
|
|||
env.assert_ok();
|
||||
|
||||
let have = env.out();
|
||||
let want = "\
|
||||
name\tfoo
|
||||
comment\tcomment
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = format!(
|
||||
"\
|
||||
name\tNAME
|
||||
comment\tCOMMENT
|
||||
creation date\t1970-01-01 00:00:01 UTC
|
||||
created by\tcreated by
|
||||
source\tsource
|
||||
info hash\te12253978dc6d50db11d05747abcea1ad03b51c5
|
||||
torrent size\t327
|
||||
content size\t20
|
||||
created by\tCREATED BY
|
||||
source\tSOURCE
|
||||
info hash\t{}
|
||||
torrent size\t{}
|
||||
content size\t32768
|
||||
private\tyes
|
||||
tracker\ta
|
||||
announce list\tx\ty\tz
|
||||
dht nodes\tx:12\t1.1.1.1:16\t[2001:db8:85a3::8a2e:370]:7334
|
||||
tracker\tudp://announce.example:1337
|
||||
announce list\thttp://a.example:4567\thttps://b.example:77\tudp://c.example:88
|
||||
update url\thttps://update.example/
|
||||
dht nodes\tnode.example:12\t1.1.1.1:16\t[2001:db8:85a3::8a2e:370]:7334
|
||||
piece size\t16384
|
||||
piece count\t2
|
||||
file count\t1
|
||||
files\tfoo
|
||||
";
|
||||
files\tNAME
|
||||
",
|
||||
Metainfo::test_value_single_infohash(),
|
||||
Metainfo::test_value_single_torrent_size().count()
|
||||
);
|
||||
|
||||
assert_eq!(have, want);
|
||||
}
|
||||
|
@ -355,31 +306,13 @@ files\tfoo
|
|||
|
||||
#[test]
|
||||
fn tier_list_without_main() -> Result<()> {
|
||||
let metainfo = Metainfo {
|
||||
announce: Some("a".into()),
|
||||
announce_list: Some(vec![vec!["b".into()], vec!["c".into()], vec!["a".into()]]),
|
||||
comment: Some("comment".into()),
|
||||
nodes: Some(vec![
|
||||
"x:12".parse().unwrap(),
|
||||
"1.1.1.1:16".parse().unwrap(),
|
||||
"[2001:0db8:85a3::8a2e:0370]:7334".parse().unwrap(),
|
||||
]),
|
||||
created_by: Some("created by".into()),
|
||||
creation_date: Some(1),
|
||||
encoding: Some("UTF-8".into()),
|
||||
info: Info {
|
||||
private: Some(true),
|
||||
piece_length: Bytes(16 * 1024),
|
||||
source: Some("source".into()),
|
||||
name: "foo".into(),
|
||||
pieces: PieceList::from_pieces(&["abc"]),
|
||||
mode: Mode::Single {
|
||||
length: Bytes(20),
|
||||
md5sum: None,
|
||||
},
|
||||
update_url: None,
|
||||
},
|
||||
};
|
||||
let mut metainfo = Metainfo::test_value_single();
|
||||
|
||||
metainfo.announce_list = Some(vec![
|
||||
vec!["B".into()],
|
||||
vec!["C".into()],
|
||||
vec!["ANNOUNCE".into()],
|
||||
]);
|
||||
|
||||
{
|
||||
let mut env = TestEnvBuilder::new()
|
||||
|
@ -394,27 +327,34 @@ files\tfoo
|
|||
env.assert_ok();
|
||||
|
||||
let have = env.out();
|
||||
let want = " Name foo
|
||||
Comment comment
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = format!(
|
||||
" Name NAME
|
||||
Comment COMMENT
|
||||
Creation Date 1970-01-01 00:00:01 UTC
|
||||
Created By created by
|
||||
Source source
|
||||
Info Hash b9cd9cae5748518c99d00d8ae86c0162510be4d9
|
||||
Torrent Size 307 bytes
|
||||
Content Size 20 bytes
|
||||
Created By CREATED BY
|
||||
Source SOURCE
|
||||
Info Hash {}
|
||||
Torrent Size {}
|
||||
Content Size 32 KiB
|
||||
Private yes
|
||||
Tracker a
|
||||
Announce List Tier 1: b
|
||||
Tier 2: c
|
||||
Tier 3: a
|
||||
DHT Nodes x:12
|
||||
Tracker udp://announce.example:1337
|
||||
Announce List Tier 1: B
|
||||
Tier 2: C
|
||||
Tier 3: ANNOUNCE
|
||||
Update URL https://update.example/
|
||||
DHT Nodes node.example:12
|
||||
1.1.1.1:16
|
||||
[2001:db8:85a3::8a2e:370]:7334
|
||||
Piece Size 16 KiB
|
||||
Piece Count 1
|
||||
Piece Count 2
|
||||
File Count 1
|
||||
Files foo
|
||||
";
|
||||
Files NAME
|
||||
",
|
||||
Metainfo::test_value_single_infohash(),
|
||||
Bytes(Metainfo::test_value_single_torrent_size().count() - 50)
|
||||
);
|
||||
|
||||
assert_eq!(have, want);
|
||||
}
|
||||
|
@ -431,24 +371,30 @@ Announce List Tier 1: b
|
|||
env.assert_ok();
|
||||
|
||||
let have = env.out();
|
||||
let want = "\
|
||||
name\tfoo
|
||||
comment\tcomment
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = format!("\
|
||||
name\tNAME
|
||||
comment\tCOMMENT
|
||||
creation date\t1970-01-01 00:00:01 UTC
|
||||
created by\tcreated by
|
||||
source\tsource
|
||||
info hash\tb9cd9cae5748518c99d00d8ae86c0162510be4d9
|
||||
torrent size\t307
|
||||
content size\t20
|
||||
created by\tCREATED BY
|
||||
source\tSOURCE
|
||||
info hash\t{}
|
||||
torrent size\t{}
|
||||
content size\t32768
|
||||
private\tyes
|
||||
tracker\ta
|
||||
announce list\tb\tc\ta
|
||||
dht nodes\tx:12\t1.1.1.1:16\t[2001:db8:85a3::8a2e:370]:7334
|
||||
tracker\tudp://announce.example:1337
|
||||
announce list\tB\tC\tANNOUNCE
|
||||
update url\thttps://update.example/
|
||||
dht nodes\tnode.example:12\t1.1.1.1:16\t[2001:db8:85a3::8a2e:370]:7334
|
||||
piece size\t16384
|
||||
piece count\t1
|
||||
piece count\t2
|
||||
file count\t1
|
||||
files\tfoo
|
||||
";
|
||||
files\tNAME
|
||||
",
|
||||
Metainfo::test_value_single_infohash(),
|
||||
Metainfo::test_value_single_torrent_size().count() - 50
|
||||
);
|
||||
|
||||
assert_eq!(have, want);
|
||||
}
|
||||
|
@ -458,31 +404,9 @@ files\tfoo
|
|||
|
||||
#[test]
|
||||
fn trackerless() -> Result<()> {
|
||||
let metainfo = Metainfo {
|
||||
announce: None,
|
||||
announce_list: None,
|
||||
comment: Some("comment".into()),
|
||||
nodes: Some(vec![
|
||||
"x:12".parse().unwrap(),
|
||||
"1.1.1.1:16".parse().unwrap(),
|
||||
"[2001:0db8:85a3::8a2e:0370]:7334".parse().unwrap(),
|
||||
]),
|
||||
created_by: Some("created by".into()),
|
||||
creation_date: Some(1),
|
||||
encoding: Some("UTF-8".into()),
|
||||
info: Info {
|
||||
private: Some(true),
|
||||
piece_length: Bytes(16 * 1024),
|
||||
source: Some("source".into()),
|
||||
name: "foo".into(),
|
||||
pieces: PieceList::from_pieces(&["abc"]),
|
||||
mode: Mode::Single {
|
||||
length: Bytes(20),
|
||||
md5sum: None,
|
||||
},
|
||||
update_url: None,
|
||||
},
|
||||
};
|
||||
let mut metainfo = Metainfo::test_value_single();
|
||||
metainfo.announce = None;
|
||||
metainfo.announce_list = None;
|
||||
|
||||
{
|
||||
let mut env = TestEnvBuilder::new()
|
||||
|
@ -497,23 +421,29 @@ files\tfoo
|
|||
env.assert_ok();
|
||||
|
||||
let have = env.out();
|
||||
let want = " Name foo
|
||||
Comment comment
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = format!(" Name NAME
|
||||
Comment COMMENT
|
||||
Creation Date 1970-01-01 00:00:01 UTC
|
||||
Created By created by
|
||||
Source source
|
||||
Info Hash b9cd9cae5748518c99d00d8ae86c0162510be4d9
|
||||
Torrent Size 261 bytes
|
||||
Content Size 20 bytes
|
||||
Created By CREATED BY
|
||||
Source SOURCE
|
||||
Info Hash {}
|
||||
Torrent Size {}
|
||||
Content Size 32 KiB
|
||||
Private yes
|
||||
DHT Nodes x:12
|
||||
Update URL https://update.example/
|
||||
DHT Nodes node.example:12
|
||||
1.1.1.1:16
|
||||
[2001:db8:85a3::8a2e:370]:7334
|
||||
Piece Size 16 KiB
|
||||
Piece Count 1
|
||||
Piece Count 2
|
||||
File Count 1
|
||||
Files foo
|
||||
";
|
||||
Files NAME
|
||||
",
|
||||
Metainfo::test_value_single_infohash(),
|
||||
Bytes(Metainfo::test_value_single_torrent_size().count() - 130)
|
||||
);
|
||||
|
||||
assert_eq!(have, want);
|
||||
}
|
||||
|
@ -530,22 +460,99 @@ Creation Date 1970-01-01 00:00:01 UTC
|
|||
env.assert_ok();
|
||||
|
||||
let have = env.out();
|
||||
let want = "\
|
||||
name\tfoo
|
||||
comment\tcomment
|
||||
#[rustfmt::skip]
|
||||
let want = format!(
|
||||
"\
|
||||
name\tNAME
|
||||
comment\tCOMMENT
|
||||
creation date\t1970-01-01 00:00:01 UTC
|
||||
created by\tcreated by
|
||||
source\tsource
|
||||
info hash\tb9cd9cae5748518c99d00d8ae86c0162510be4d9
|
||||
torrent size\t261
|
||||
content size\t20
|
||||
created by\tCREATED BY
|
||||
source\tSOURCE
|
||||
info hash\t{}
|
||||
torrent size\t{}
|
||||
content size\t32768
|
||||
private\tyes
|
||||
dht nodes\tx:12\t1.1.1.1:16\t[2001:db8:85a3::8a2e:370]:7334
|
||||
update url\thttps://update.example/
|
||||
dht nodes\tnode.example:12\t1.1.1.1:16\t[2001:db8:85a3::8a2e:370]:7334
|
||||
piece size\t16384
|
||||
piece count\t2
|
||||
file count\t1
|
||||
files\tNAME
|
||||
",
|
||||
Metainfo::test_value_single_infohash(),
|
||||
Metainfo::test_value_single_torrent_size().count() - 130
|
||||
);
|
||||
|
||||
assert_eq!(have, want);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unset() -> Result<()> {
|
||||
let metainfo = Metainfo::test_value_single_unset();
|
||||
|
||||
{
|
||||
let mut env = TestEnvBuilder::new()
|
||||
.arg_slice(&["imdl", "torrent", "show", "--input", "foo.torrent"])
|
||||
.out_is_term()
|
||||
.build();
|
||||
|
||||
let path = env.resolve("foo.torrent")?;
|
||||
|
||||
metainfo.dump(path).unwrap();
|
||||
|
||||
env.assert_ok();
|
||||
|
||||
let have = env.out();
|
||||
|
||||
#[rustfmt::skip]
|
||||
let want = format!(" Name NAME
|
||||
Info Hash {}
|
||||
Torrent Size {}
|
||||
Content Size 5 bytes
|
||||
Private no
|
||||
Piece Size 1 KiB
|
||||
Piece Count 1
|
||||
File Count 1
|
||||
Files NAME
|
||||
",
|
||||
Metainfo::test_value_single_unset_infohash(),
|
||||
Metainfo::test_value_single_unset_torrent_size()
|
||||
);
|
||||
|
||||
assert_eq!(have, want);
|
||||
}
|
||||
|
||||
{
|
||||
let mut env = TestEnvBuilder::new()
|
||||
.arg_slice(&["imdl", "torrent", "show", "--input", "foo.torrent"])
|
||||
.build();
|
||||
|
||||
let path = env.resolve("foo.torrent")?;
|
||||
|
||||
metainfo.dump(path).unwrap();
|
||||
|
||||
env.assert_ok();
|
||||
|
||||
let have = env.out();
|
||||
#[rustfmt::skip]
|
||||
let want = format!(
|
||||
"\
|
||||
name\tNAME
|
||||
info hash\t{}
|
||||
torrent size\t{}
|
||||
content size\t5
|
||||
private\tno
|
||||
piece size\t1024
|
||||
piece count\t1
|
||||
file count\t1
|
||||
files\tfoo
|
||||
";
|
||||
files\tNAME
|
||||
",
|
||||
Metainfo::test_value_single_unset_infohash(),
|
||||
Metainfo::test_value_single_unset_torrent_size().count()
|
||||
);
|
||||
|
||||
assert_eq!(have, want);
|
||||
}
|
||||
|
|
|
@ -105,6 +105,10 @@ impl TorrentSummary {
|
|||
table.tiers("Announce List", value);
|
||||
}
|
||||
|
||||
if let Some(update_url) = &self.metainfo.info.update_url {
|
||||
table.row("Update URL", update_url);
|
||||
}
|
||||
|
||||
if let Some(nodes) = &self.metainfo.nodes {
|
||||
table.list(
|
||||
"DHT Nodes",
|
||||
|
|
Loading…
Reference in New Issue
Block a user