1use super::Database;
2use crate::{
3 db::{queries::extensions::convert_time_to_chrono, ExtensionMetadata, NewExtensionVersion},
4 test_both_dbs,
5};
6use std::sync::Arc;
7
8test_both_dbs!(
9 test_extensions,
10 test_extensions_postgres,
11 test_extensions_sqlite
12);
13
14async fn test_extensions(db: &Arc<Database>) {
15 let versions = db.get_known_extension_versions().await.unwrap();
16 assert!(versions.is_empty());
17
18 let extensions = db.get_extensions(None, 1, 5).await.unwrap();
19 assert!(extensions.is_empty());
20
21 let t0 = time::OffsetDateTime::from_unix_timestamp_nanos(0).unwrap();
22 let t0 = time::PrimitiveDateTime::new(t0.date(), t0.time());
23
24 let t0_chrono = convert_time_to_chrono(t0);
25
26 db.insert_extension_versions(
27 &[
28 (
29 "ext1",
30 vec![
31 NewExtensionVersion {
32 name: "Extension 1".into(),
33 version: semver::Version::parse("0.0.1").unwrap(),
34 description: "an extension".into(),
35 authors: vec!["max".into()],
36 repository: "ext1/repo".into(),
37 schema_version: 1,
38 wasm_api_version: None,
39 published_at: t0,
40 },
41 NewExtensionVersion {
42 name: "Extension One".into(),
43 version: semver::Version::parse("0.0.2").unwrap(),
44 description: "a good extension".into(),
45 authors: vec!["max".into(), "marshall".into()],
46 repository: "ext1/repo".into(),
47 schema_version: 1,
48 wasm_api_version: None,
49 published_at: t0,
50 },
51 ],
52 ),
53 (
54 "ext2",
55 vec![NewExtensionVersion {
56 name: "Extension Two".into(),
57 version: semver::Version::parse("0.2.0").unwrap(),
58 description: "a great extension".into(),
59 authors: vec!["marshall".into()],
60 repository: "ext2/repo".into(),
61 schema_version: 0,
62 wasm_api_version: None,
63 published_at: t0,
64 }],
65 ),
66 ]
67 .into_iter()
68 .collect(),
69 )
70 .await
71 .unwrap();
72
73 let versions = db.get_known_extension_versions().await.unwrap();
74 assert_eq!(
75 versions,
76 [
77 ("ext1".into(), vec!["0.0.1".into(), "0.0.2".into()]),
78 ("ext2".into(), vec!["0.2.0".into()])
79 ]
80 .into_iter()
81 .collect()
82 );
83
84 // The latest version of each extension is returned.
85 let extensions = db.get_extensions(None, 1, 5).await.unwrap();
86 assert_eq!(
87 extensions,
88 &[
89 ExtensionMetadata {
90 id: "ext1".into(),
91 manifest: rpc::ExtensionApiManifest {
92 name: "Extension One".into(),
93 version: "0.0.2".into(),
94 authors: vec!["max".into(), "marshall".into()],
95 description: Some("a good extension".into()),
96 repository: "ext1/repo".into(),
97 schema_version: Some(1),
98 wasm_api_version: None,
99 },
100 published_at: t0_chrono,
101 download_count: 0,
102 },
103 ExtensionMetadata {
104 id: "ext2".into(),
105 manifest: rpc::ExtensionApiManifest {
106 name: "Extension Two".into(),
107 version: "0.2.0".into(),
108 authors: vec!["marshall".into()],
109 description: Some("a great extension".into()),
110 repository: "ext2/repo".into(),
111 schema_version: Some(0),
112 wasm_api_version: None,
113 },
114 published_at: t0_chrono,
115 download_count: 0
116 },
117 ]
118 );
119
120 // Extensions with too new of a schema version are excluded.
121 let extensions = db.get_extensions(None, 0, 5).await.unwrap();
122 assert_eq!(
123 extensions,
124 &[ExtensionMetadata {
125 id: "ext2".into(),
126 manifest: rpc::ExtensionApiManifest {
127 name: "Extension Two".into(),
128 version: "0.2.0".into(),
129 authors: vec!["marshall".into()],
130 description: Some("a great extension".into()),
131 repository: "ext2/repo".into(),
132 schema_version: Some(0),
133 wasm_api_version: None,
134 },
135 published_at: t0_chrono,
136 download_count: 0
137 },]
138 );
139
140 // Record extensions being downloaded.
141 for _ in 0..7 {
142 assert!(db.record_extension_download("ext2", "0.0.2").await.unwrap());
143 }
144
145 for _ in 0..3 {
146 assert!(db.record_extension_download("ext1", "0.0.1").await.unwrap());
147 }
148
149 for _ in 0..2 {
150 assert!(db.record_extension_download("ext1", "0.0.2").await.unwrap());
151 }
152
153 // Record download returns false if the extension does not exist.
154 assert!(!db
155 .record_extension_download("no-such-extension", "0.0.2")
156 .await
157 .unwrap());
158
159 // Extensions are returned in descending order of total downloads.
160 let extensions = db.get_extensions(None, 1, 5).await.unwrap();
161 assert_eq!(
162 extensions,
163 &[
164 ExtensionMetadata {
165 id: "ext2".into(),
166 manifest: rpc::ExtensionApiManifest {
167 name: "Extension Two".into(),
168 version: "0.2.0".into(),
169 authors: vec!["marshall".into()],
170 description: Some("a great extension".into()),
171 repository: "ext2/repo".into(),
172 schema_version: Some(0),
173 wasm_api_version: None,
174 },
175 published_at: t0_chrono,
176 download_count: 7
177 },
178 ExtensionMetadata {
179 id: "ext1".into(),
180 manifest: rpc::ExtensionApiManifest {
181 name: "Extension One".into(),
182 version: "0.0.2".into(),
183 authors: vec!["max".into(), "marshall".into()],
184 description: Some("a good extension".into()),
185 repository: "ext1/repo".into(),
186 schema_version: Some(1),
187 wasm_api_version: None,
188 },
189 published_at: t0_chrono,
190 download_count: 5,
191 },
192 ]
193 );
194
195 // Add more extensions, including a new version of `ext1`, and backfilling
196 // an older version of `ext2`.
197 db.insert_extension_versions(
198 &[
199 (
200 "ext1",
201 vec![NewExtensionVersion {
202 name: "Extension One".into(),
203 version: semver::Version::parse("0.0.3").unwrap(),
204 description: "a real good extension".into(),
205 authors: vec!["max".into(), "marshall".into()],
206 repository: "ext1/repo".into(),
207 schema_version: 1,
208 wasm_api_version: None,
209 published_at: t0,
210 }],
211 ),
212 (
213 "ext2",
214 vec![NewExtensionVersion {
215 name: "Extension Two".into(),
216 version: semver::Version::parse("0.1.0").unwrap(),
217 description: "an old extension".into(),
218 authors: vec!["marshall".into()],
219 repository: "ext2/repo".into(),
220 schema_version: 0,
221 wasm_api_version: None,
222 published_at: t0,
223 }],
224 ),
225 ]
226 .into_iter()
227 .collect(),
228 )
229 .await
230 .unwrap();
231
232 let versions = db.get_known_extension_versions().await.unwrap();
233 assert_eq!(
234 versions,
235 [
236 (
237 "ext1".into(),
238 vec!["0.0.1".into(), "0.0.2".into(), "0.0.3".into()]
239 ),
240 ("ext2".into(), vec!["0.1.0".into(), "0.2.0".into()])
241 ]
242 .into_iter()
243 .collect()
244 );
245
246 let extensions = db.get_extensions(None, 1, 5).await.unwrap();
247 assert_eq!(
248 extensions,
249 &[
250 ExtensionMetadata {
251 id: "ext2".into(),
252 manifest: rpc::ExtensionApiManifest {
253 name: "Extension Two".into(),
254 version: "0.2.0".into(),
255 authors: vec!["marshall".into()],
256 description: Some("a great extension".into()),
257 repository: "ext2/repo".into(),
258 schema_version: Some(0),
259 wasm_api_version: None,
260 },
261 published_at: t0_chrono,
262 download_count: 7
263 },
264 ExtensionMetadata {
265 id: "ext1".into(),
266 manifest: rpc::ExtensionApiManifest {
267 name: "Extension One".into(),
268 version: "0.0.3".into(),
269 authors: vec!["max".into(), "marshall".into()],
270 description: Some("a real good extension".into()),
271 repository: "ext1/repo".into(),
272 schema_version: Some(1),
273 wasm_api_version: None,
274 },
275 published_at: t0_chrono,
276 download_count: 5,
277 },
278 ]
279 );
280}