History

[git-protocol] move everything into `blocking_io` for later translation…

…into async-io, as usual.

Sebastian Thiel committed 5 years ago

Commit fa033741 parent 0d39b5d12 files · +295 −254Browse files

Showing the changes to git-protocol/src/fetch/tests (4 of 12 files). Show all

Unified · Split

4 files
  1. git-protocol/src/fetch/tests/arguments.rs +0 −236
  2. git-protocol/src/fetch/tests/command.rs +0 −162
  3. git-protocol/src/fetch/tests/mod.rs +0 −3
  4. git-protocol/src/fetch/tests/refs.rs +0 −106
git-protocol/src/fetch/tests/arguments.rs+0−236
@@ -1,236 +0,0 @@
1use crate::fetch;
2use bstr::ByteSlice;
3use git_transport::{
4 client,
5 client::{Error, Identity, MessageKind, RequestWriter, SetServiceResponse, WriteMode},
6 Protocol, Service,
7};
8use std::io;
9
10fn arguments_v1(features: impl IntoIterator<Item = &'static str>) -> fetch::Arguments {
11 fetch::Arguments::new(Protocol::V1, features.into_iter().map(|n| (n, None)).collect())
12}
13
14fn arguments_v2(features: impl IntoIterator<Item = &'static str>) -> fetch::Arguments {
15 fetch::Arguments::new(Protocol::V2, features.into_iter().map(|n| (n, None)).collect())
16}
17
18struct Transport<T: client::Transport> {
19 inner: T,
20 stateful: bool,
21}
22
23impl<T: client::Transport> client::Transport for Transport<T> {
24 fn handshake(&mut self, service: Service) -> Result<SetServiceResponse<'_>, Error> {
25 self.inner.handshake(service)
26 }
27
28 fn set_identity(&mut self, identity: Identity) -> Result<(), Error> {
29 self.inner.set_identity(identity)
30 }
31
32 fn request(&mut self, write_mode: WriteMode, on_into_read: MessageKind) -> Result<RequestWriter<'_>, Error> {
33 self.inner.request(write_mode, on_into_read)
34 }
35
36 fn close(&mut self) -> Result<(), Error> {
37 self.inner.close()
38 }
39
40 fn to_url(&self) -> String {
41 self.inner.to_url()
42 }
43
44 fn desired_protocol_version(&self) -> Protocol {
45 self.inner.desired_protocol_version()
46 }
47
48 fn is_stateful(&self) -> bool {
49 self.stateful
50 }
51}
52
53fn transport(
54 out: &mut Vec<u8>,
55 stateful: bool,
56) -> Transport<git_transport::client::git::Connection<io::Cursor<Vec<u8>>, &mut Vec<u8>>> {
57 Transport {
58 inner: git_transport::client::git::Connection::new(
59 io::Cursor::new(Vec::new()),
60 out,
61 Protocol::V1, // does not matter
62 b"does/not/matter".as_bstr().to_owned(),
63 None::<(&str, _)>,
64 git_transport::client::git::ConnectMode::Process, // avoid header to be sent
65 ),
66 stateful,
67 }
68}
69
70fn id(hex: &str) -> git_hash::ObjectId {
71 git_hash::ObjectId::from_hex(hex.as_bytes()).expect("expect valid hex id")
72}
73
74mod v1 {
75 use crate::fetch::tests::arguments::{arguments_v1, id, transport};
76 use bstr::ByteSlice;
77
78 #[test]
79 fn haves_and_wants_for_clone() {
80 let mut out = Vec::new();
81 let mut t = transport(&mut out, true);
82 let mut arguments = arguments_v1(["feature-a", "feature-b"].iter().cloned());
83
84 arguments.want(id("7b333369de1221f9bfbbe03a3a13e9a09bc1c907"));
85 arguments.want(id("ff333369de1221f9bfbbe03a3a13e9a09bc1ffff"));
86 arguments.send(&mut t, true).expect("sending to buffer to work");
87 assert_eq!(
88 out.as_bstr(),
89 b"0046want 7b333369de1221f9bfbbe03a3a13e9a09bc1c907 feature-a feature-b
900032want ff333369de1221f9bfbbe03a3a13e9a09bc1ffff
9100000009done
92"
93 .as_bstr()
94 );
95 }
96
97 #[test]
98 fn haves_and_wants_for_fetch_stateless() {
99 let mut out = Vec::new();
100 let mut t = transport(&mut out, false);
101 let mut arguments = arguments_v1(["feature-a", "shallow", "deepen-since", "deepen-not"].iter().copied());
102
103 arguments.deepen(1);
104 arguments.shallow(id("7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff"));
105 arguments.want(id("7b333369de1221f9bfbbe03a3a13e9a09bc1c907"));
106 arguments.deepen_since(12345);
107 arguments.deepen_not("refs/heads/main".into());
108 arguments.have(id("0000000000000000000000000000000000000000"));
109 arguments.send(&mut t, false).expect("sending to buffer to work");
110
111 arguments.have(id("1111111111111111111111111111111111111111"));
112 arguments.send(&mut t, true).expect("sending to buffer to work");
113 assert_eq!(
114 out.as_bstr(),
115 b"005cwant 7b333369de1221f9bfbbe03a3a13e9a09bc1c907 feature-a shallow deepen-since deepen-not
1160035shallow 7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff
117000ddeepen 1
1180017deepen-since 12345
119001fdeepen-not refs/heads/main
12000000032have 0000000000000000000000000000000000000000
1210000005cwant 7b333369de1221f9bfbbe03a3a13e9a09bc1c907 feature-a shallow deepen-since deepen-not
1220035shallow 7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff
123000ddeepen 1
1240017deepen-since 12345
125001fdeepen-not refs/heads/main
12600000032have 1111111111111111111111111111111111111111
1270009done
128"
129 .as_bstr()
130 );
131 }
132
133 #[test]
134 fn haves_and_wants_for_fetch_stateful() {
135 let mut out = Vec::new();
136 let mut t = transport(&mut out, true);
137 let mut arguments = arguments_v1(["feature-a", "shallow"].iter().copied());
138
139 arguments.deepen(1);
140 arguments.want(id("7b333369de1221f9bfbbe03a3a13e9a09bc1c907"));
141 arguments.have(id("0000000000000000000000000000000000000000"));
142 arguments.send(&mut t, false).expect("sending to buffer to work");
143
144 arguments.have(id("1111111111111111111111111111111111111111"));
145 arguments.send(&mut t, true).expect("sending to buffer to work");
146 assert_eq!(
147 out.as_bstr(),
148 b"0044want 7b333369de1221f9bfbbe03a3a13e9a09bc1c907 feature-a shallow
149000ddeepen 1
15000000032have 0000000000000000000000000000000000000000
15100000032have 1111111111111111111111111111111111111111
1520009done
153"
154 .as_bstr()
155 );
156 }
157}
158
159mod v2 {
160 use crate::fetch::tests::arguments::{arguments_v2, id, transport};
161 use bstr::ByteSlice;
162
163 #[test]
164 fn haves_and_wants_for_clone_stateful() {
165 let mut out = Vec::new();
166 let mut t = transport(&mut out, true);
167 let mut arguments = arguments_v2(["feature-a", "shallow"].iter().copied());
168
169 arguments.deepen(1);
170 arguments.deepen_relative();
171 arguments.want(id("7b333369de1221f9bfbbe03a3a13e9a09bc1c907"));
172 arguments.want(id("ff333369de1221f9bfbbe03a3a13e9a09bc1ffff"));
173 arguments.send(&mut t, true).expect("sending to buffer to work");
174 assert_eq!(
175 out.as_bstr(),
176 b"0012command=fetch
1770001000ethin-pack
1780010include-tag
179000eofs-delta
180000ddeepen 1
1810014deepen-relative
1820032want 7b333369de1221f9bfbbe03a3a13e9a09bc1c907
1830032want ff333369de1221f9bfbbe03a3a13e9a09bc1ffff
1840009done
1850000"
186 .as_bstr(), "we filter features/capabilities without value as these apparently sholdn't be listed (remote dies otherwise)"
187 );
188 }
189
190 #[test]
191 fn haves_and_wants_for_fetch_stateless_and_stateful() {
192 for is_stateful in &[false, true] {
193 let mut out = Vec::new();
194 let mut t = transport(&mut out, *is_stateful);
195 let mut arguments = arguments_v2(Some("shallow"));
196
197 arguments.deepen(1);
198 arguments.deepen_since(12345);
199 arguments.shallow(id("7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff"));
200 arguments.want(id("7b333369de1221f9bfbbe03a3a13e9a09bc1c907"));
201 arguments.deepen_not("refs/heads/main".into());
202 arguments.have(id("0000000000000000000000000000000000000000"));
203 arguments.send(&mut t, false).expect("sending to buffer to work");
204
205 arguments.have(id("1111111111111111111111111111111111111111"));
206 arguments.send(&mut t, true).expect("sending to buffer to work");
207 assert_eq!(
208 out.as_bstr(),
209 b"0012command=fetch
2100001000ethin-pack
2110010include-tag
212000eofs-delta
213000ddeepen 1
2140017deepen-since 12345
2150035shallow 7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff
2160032want 7b333369de1221f9bfbbe03a3a13e9a09bc1c907
217001fdeepen-not refs/heads/main
2180032have 0000000000000000000000000000000000000000
21900000012command=fetch
2200001000ethin-pack
2210010include-tag
222000eofs-delta
223000ddeepen 1
2240017deepen-since 12345
2250035shallow 7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff
2260032want 7b333369de1221f9bfbbe03a3a13e9a09bc1c907
227001fdeepen-not refs/heads/main
2280032have 1111111111111111111111111111111111111111
2290009done
2300000"
231 .as_bstr(),
232 "V2 is stateless by default, so it repeats all but 'haves' in each request"
233 );
234 }
235 }
236}
git-protocol/src/fetch/tests/command.rs+0−162
@@ -1,162 +0,0 @@
1mod v1 {
2 fn capabilities(input: &str) -> git_transport::client::Capabilities {
3 git_transport::client::Capabilities::from_bytes(format!("\0{}", input).as_bytes())
4 .expect("valid input capabilities")
5 .0
6 }
7
8 const GITHUB_CAPABILITIES: &str = "multi_ack thin-pack side-band ofs-delta shallow deepen-since deepen-not deepen-relative no-progress include-tag allow-tip-sha1-in-want allow-reachable-sha1-in-want no-done symref=HEAD:refs/heads/main filter agent=git/github-gdf51a71f0236";
9 mod fetch {
10 mod default_features {
11 use crate::fetch::{
12 self,
13 tests::command::v1::{capabilities, GITHUB_CAPABILITIES},
14 Command,
15 };
16
17 #[test]
18 fn it_chooses_the_best_multi_ack_and_sideband() {
19 assert_eq!(
20 Command::Fetch.default_features(
21 git_transport::Protocol::V1,
22 &capabilities("multi_ack side-band side-band-64k multi_ack_detailed")
23 ),
24 &[("side-band-64k", None), ("multi_ack_detailed", None), fetch::agent()]
25 );
26 }
27
28 #[test]
29 fn it_chooses_all_supported_non_stacking_capabilities_and_leaves_no_progress() {
30 assert_eq!(
31 Command::Fetch.default_features(git_transport::Protocol::V1, &capabilities(GITHUB_CAPABILITIES)),
32 &[
33 ("multi_ack", None),
34 ("thin-pack", None),
35 ("side-band", None),
36 ("ofs-delta", None),
37 ("shallow", None),
38 ("deepen-since", None),
39 ("deepen-not", None),
40 ("deepen-relative", None),
41 ("allow-tip-sha1-in-want", None),
42 ("allow-reachable-sha1-in-want", None),
43 ("no-done", None),
44 ("filter", None),
45 fetch::agent()
46 ],
47 "we don't enforce include-tag or no-progress"
48 );
49 }
50 }
51 }
52}
53
54mod v2 {
55 use git_transport::client::Capabilities;
56
57 fn capabilities(command: &str, input: &str) -> Capabilities {
58 Capabilities::from_lines(Some(Ok("version 2".into())), format!("{}={}", command, input))
59 .expect("valid input for V2 capabilities")
60 }
61
62 mod fetch {
63 mod default_features {
64 use crate::fetch::{self, tests::command::v2::capabilities, Command};
65
66 #[test]
67 fn all_features() {
68 assert_eq!(
69 Command::Fetch.default_features(
70 git_transport::Protocol::V2,
71 &capabilities("fetch", "shallow filter ref-in-want sideband-all packfile-uris")
72 ),
73 ["shallow", "filter", "ref-in-want", "sideband-all", "packfile-uris"]
74 .iter()
75 .map(|s| (*s, None))
76 .chain(Some(fetch::agent()))
77 .collect::<Vec<_>>()
78 )
79 }
80 }
81
82 mod initial_arguments {
83 use crate::fetch::{tests::command::v2::capabilities, Command};
84 use bstr::ByteSlice;
85
86 #[test]
87 fn for_all_features() {
88 assert_eq!(
89 Command::Fetch.initial_arguments(&Command::Fetch.default_features(
90 git_transport::Protocol::V2,
91 &capabilities("fetch", "shallow filter ref-in-want sideband-all packfile-uris")
92 )),
93 [
94 "thin-pack",
95 "include-tag",
96 "ofs-delta",
97 "sideband-all",
98 "ref-in-want",
99 "packfile-uris"
100 ]
101 .iter()
102 .map(|s| s.as_bytes().as_bstr().to_owned())
103 .collect::<Vec<_>>()
104 )
105 }
106 }
107 }
108
109 mod ls_refs {
110 mod default_features {
111 use crate::fetch::{self, tests::command::v2::capabilities, Command};
112
113 #[test]
114 fn default_as_there_are_no_features() {
115 assert_eq!(
116 Command::LsRefs.default_features(
117 git_transport::Protocol::V2,
118 &capabilities("something-else", "does not matter as there are none")
119 ),
120 &[fetch::agent()]
121 );
122 }
123 }
124
125 mod validate {
126 use crate::fetch::{tests::command::v2::capabilities, Command};
127 use bstr::ByteSlice;
128
129 #[test]
130 fn ref_prefixes_can_always_be_used() {
131 Command::LsRefs.validate_argument_prefixes_or_panic(
132 git_transport::Protocol::V2,
133 &capabilities("something else", "do-not-matter"),
134 &[b"ref-prefix hello/".as_bstr().into()],
135 &[],
136 );
137 }
138
139 #[test]
140 #[should_panic]
141 fn unknown_argument() {
142 Command::LsRefs.validate_argument_prefixes_or_panic(
143 git_transport::Protocol::V2,
144 &capabilities("other", "do-not-matter"),
145 &[b"definitely-nothing-we-know".as_bstr().into()],
146 &[],
147 );
148 }
149
150 #[test]
151 #[should_panic]
152 fn unknown_feature() {
153 Command::LsRefs.validate_argument_prefixes_or_panic(
154 git_transport::Protocol::V2,
155 &capabilities("other", "do-not-matter"),
156 &[],
157 &[("some-feature-that-does-not-exist", None)],
158 );
159 }
160 }
161 }
162}
git-protocol/src/fetch/tests/mod.rs+0−3
@@ -1,3 +0,0 @@
1mod arguments;
2mod command;
3mod refs;
git-protocol/src/fetch/tests/refs.rs+0−106
@@ -1,106 +0,0 @@
1use super::super::{refs, InternalRef, Ref};
2use git_transport::client;
3use std::io;
4
5fn oid(hex_sha: &str) -> git_hash::ObjectId {
6 git_hash::ObjectId::from_hex(hex_sha.as_bytes()).expect("valid input")
7}
8
9#[test]
10fn extract_references_from_v2_refs() {
11 let input: &mut dyn io::BufRead = &mut "808e50d724f604f69ab93c6da2919c014667bedb HEAD symref-target:refs/heads/main
12808e50d724f604f69ab93c6da2919c014667bedb refs/heads/main
137fe1b98b39423b71e14217aa299a03b7c937d656 refs/tags/foo peeled:808e50d724f604f69ab93c6da2919c014667bedb
147fe1b98b39423b71e14217aa299a03b7c937d6ff refs/tags/blaz
15"
16 .as_bytes();
17 let mut out = Vec::new();
18 refs::from_v2_refs(&mut out, input).expect("no failure on valid input");
19
20 assert_eq!(
21 out,
22 vec![
23 Ref::Symbolic {
24 path: "HEAD".into(),
25 target: "refs/heads/main".into(),
26 object: oid("808e50d724f604f69ab93c6da2919c014667bedb")
27 },
28 Ref::Direct {
29 path: "refs/heads/main".into(),
30 object: oid("808e50d724f604f69ab93c6da2919c014667bedb")
31 },
32 Ref::Peeled {
33 path: "refs/tags/foo".into(),
34 tag: oid("7fe1b98b39423b71e14217aa299a03b7c937d656"),
35 object: oid("808e50d724f604f69ab93c6da2919c014667bedb")
36 },
37 Ref::Direct {
38 path: "refs/tags/blaz".into(),
39 object: oid("7fe1b98b39423b71e14217aa299a03b7c937d6ff")
40 },
41 ]
42 )
43}
44
45#[test]
46fn extract_references_from_v1_refs() {
47 let input: &mut dyn io::BufRead = &mut "73a6868963993a3328e7d8fe94e5a6ac5078a944 HEAD
4873a6868963993a3328e7d8fe94e5a6ac5078a944 refs/heads/main
498e472f9ccc7d745927426cbb2d9d077de545aa4e refs/pull/13/head
50dce0ea858eef7ff61ad345cc5cdac62203fb3c10 refs/tags/git-commitgraph-v0.0.0
5121c9b7500cb144b3169a6537961ec2b9e865be81 refs/tags/git-commitgraph-v0.0.0^{}"
52 .as_bytes();
53 let mut out = vec![InternalRef::SymbolicForLookup {
54 path: "HEAD".into(),
55 target: "refs/heads/main".into(),
56 }];
57 refs::from_v1_refs_received_as_part_of_handshake(&mut out, input).expect("no failure from valid input");
58 assert_eq!(
59 out,
60 vec![
61 InternalRef::Symbolic {
62 path: "HEAD".into(),
63 target: "refs/heads/main".into(),
64 object: oid("73a6868963993a3328e7d8fe94e5a6ac5078a944")
65 },
66 InternalRef::Direct {
67 path: "refs/heads/main".into(),
68 object: oid("73a6868963993a3328e7d8fe94e5a6ac5078a944")
69 },
70 InternalRef::Direct {
71 path: "refs/pull/13/head".into(),
72 object: oid("8e472f9ccc7d745927426cbb2d9d077de545aa4e")
73 },
74 InternalRef::Peeled {
75 path: "refs/tags/git-commitgraph-v0.0.0".into(),
76 tag: oid("dce0ea858eef7ff61ad345cc5cdac62203fb3c10"),
77 object: oid("21c9b7500cb144b3169a6537961ec2b9e865be81")
78 }
79 ]
80 )
81}
82
83#[test]
84fn extract_symbolic_references_from_capabilities() -> Result<(), client::Error> {
85 let caps = client::Capabilities::from_bytes(
86 b"\0unrelated symref=HEAD:refs/heads/main symref=ANOTHER:refs/heads/foo agent=git/2.28.0",
87 )?
88 .0;
89 let mut out = Vec::new();
90 refs::from_capabilities(&mut out, caps.iter()).expect("a working example");
91
92 assert_eq!(
93 out,
94 vec![
95 InternalRef::SymbolicForLookup {
96 path: "HEAD".into(),
97 target: "refs/heads/main".into()
98 },
99 InternalRef::SymbolicForLookup {
100 path: "ANOTHER".into(),
101 target: "refs/heads/foo".into()
102 }
103 ]
104 );
105 Ok(())
106}