extension_tests.rs

  1use super::Database;
  2use crate::db::ExtensionVersionConstraints;
  3use crate::{
  4    db::{queries::extensions::convert_time_to_chrono, ExtensionMetadata, NewExtensionVersion},
  5    test_both_dbs,
  6};
  7use std::sync::Arc;
  8
  9test_both_dbs!(
 10    test_extensions,
 11    test_extensions_postgres,
 12    test_extensions_sqlite
 13);
 14
 15async fn test_extensions(db: &Arc<Database>) {
 16    let versions = db.get_known_extension_versions().await.unwrap();
 17    assert!(versions.is_empty());
 18
 19    let extensions = db.get_extensions(None, 1, 5).await.unwrap();
 20    assert!(extensions.is_empty());
 21
 22    let t0 = time::OffsetDateTime::from_unix_timestamp_nanos(0).unwrap();
 23    let t0 = time::PrimitiveDateTime::new(t0.date(), t0.time());
 24
 25    let t0_chrono = convert_time_to_chrono(t0);
 26
 27    db.insert_extension_versions(
 28        &[
 29            (
 30                "ext1",
 31                vec![
 32                    NewExtensionVersion {
 33                        name: "Extension 1".into(),
 34                        version: semver::Version::parse("0.0.1").unwrap(),
 35                        description: "an extension".into(),
 36                        authors: vec!["max".into()],
 37                        repository: "ext1/repo".into(),
 38                        schema_version: 1,
 39                        wasm_api_version: None,
 40                        published_at: t0,
 41                    },
 42                    NewExtensionVersion {
 43                        name: "Extension One".into(),
 44                        version: semver::Version::parse("0.0.2").unwrap(),
 45                        description: "a good extension".into(),
 46                        authors: vec!["max".into(), "marshall".into()],
 47                        repository: "ext1/repo".into(),
 48                        schema_version: 1,
 49                        wasm_api_version: None,
 50                        published_at: t0,
 51                    },
 52                ],
 53            ),
 54            (
 55                "ext2",
 56                vec![NewExtensionVersion {
 57                    name: "Extension Two".into(),
 58                    version: semver::Version::parse("0.2.0").unwrap(),
 59                    description: "a great extension".into(),
 60                    authors: vec!["marshall".into()],
 61                    repository: "ext2/repo".into(),
 62                    schema_version: 0,
 63                    wasm_api_version: None,
 64                    published_at: t0,
 65                }],
 66            ),
 67        ]
 68        .into_iter()
 69        .collect(),
 70    )
 71    .await
 72    .unwrap();
 73
 74    let versions = db.get_known_extension_versions().await.unwrap();
 75    assert_eq!(
 76        versions,
 77        [
 78            ("ext1".into(), vec!["0.0.1".into(), "0.0.2".into()]),
 79            ("ext2".into(), vec!["0.2.0".into()])
 80        ]
 81        .into_iter()
 82        .collect()
 83    );
 84
 85    // The latest version of each extension is returned.
 86    let extensions = db.get_extensions(None, 1, 5).await.unwrap();
 87    assert_eq!(
 88        extensions,
 89        &[
 90            ExtensionMetadata {
 91                id: "ext1".into(),
 92                manifest: rpc::ExtensionApiManifest {
 93                    name: "Extension One".into(),
 94                    version: "0.0.2".into(),
 95                    authors: vec!["max".into(), "marshall".into()],
 96                    description: Some("a good extension".into()),
 97                    repository: "ext1/repo".into(),
 98                    schema_version: Some(1),
 99                    wasm_api_version: None,
100                },
101                published_at: t0_chrono,
102                download_count: 0,
103            },
104            ExtensionMetadata {
105                id: "ext2".into(),
106                manifest: rpc::ExtensionApiManifest {
107                    name: "Extension Two".into(),
108                    version: "0.2.0".into(),
109                    authors: vec!["marshall".into()],
110                    description: Some("a great extension".into()),
111                    repository: "ext2/repo".into(),
112                    schema_version: Some(0),
113                    wasm_api_version: None,
114                },
115                published_at: t0_chrono,
116                download_count: 0
117            },
118        ]
119    );
120
121    // Extensions with too new of a schema version are excluded.
122    let extensions = db.get_extensions(None, 0, 5).await.unwrap();
123    assert_eq!(
124        extensions,
125        &[ExtensionMetadata {
126            id: "ext2".into(),
127            manifest: rpc::ExtensionApiManifest {
128                name: "Extension Two".into(),
129                version: "0.2.0".into(),
130                authors: vec!["marshall".into()],
131                description: Some("a great extension".into()),
132                repository: "ext2/repo".into(),
133                schema_version: Some(0),
134                wasm_api_version: None,
135            },
136            published_at: t0_chrono,
137            download_count: 0
138        },]
139    );
140
141    // Record extensions being downloaded.
142    for _ in 0..7 {
143        assert!(db.record_extension_download("ext2", "0.0.2").await.unwrap());
144    }
145
146    for _ in 0..3 {
147        assert!(db.record_extension_download("ext1", "0.0.1").await.unwrap());
148    }
149
150    for _ in 0..2 {
151        assert!(db.record_extension_download("ext1", "0.0.2").await.unwrap());
152    }
153
154    // Record download returns false if the extension does not exist.
155    assert!(!db
156        .record_extension_download("no-such-extension", "0.0.2")
157        .await
158        .unwrap());
159
160    // Extensions are returned in descending order of total downloads.
161    let extensions = db.get_extensions(None, 1, 5).await.unwrap();
162    assert_eq!(
163        extensions,
164        &[
165            ExtensionMetadata {
166                id: "ext2".into(),
167                manifest: rpc::ExtensionApiManifest {
168                    name: "Extension Two".into(),
169                    version: "0.2.0".into(),
170                    authors: vec!["marshall".into()],
171                    description: Some("a great extension".into()),
172                    repository: "ext2/repo".into(),
173                    schema_version: Some(0),
174                    wasm_api_version: None,
175                },
176                published_at: t0_chrono,
177                download_count: 7
178            },
179            ExtensionMetadata {
180                id: "ext1".into(),
181                manifest: rpc::ExtensionApiManifest {
182                    name: "Extension One".into(),
183                    version: "0.0.2".into(),
184                    authors: vec!["max".into(), "marshall".into()],
185                    description: Some("a good extension".into()),
186                    repository: "ext1/repo".into(),
187                    schema_version: Some(1),
188                    wasm_api_version: None,
189                },
190                published_at: t0_chrono,
191                download_count: 5,
192            },
193        ]
194    );
195
196    // Add more extensions, including a new version of `ext1`, and backfilling
197    // an older version of `ext2`.
198    db.insert_extension_versions(
199        &[
200            (
201                "ext1",
202                vec![NewExtensionVersion {
203                    name: "Extension One".into(),
204                    version: semver::Version::parse("0.0.3").unwrap(),
205                    description: "a real good extension".into(),
206                    authors: vec!["max".into(), "marshall".into()],
207                    repository: "ext1/repo".into(),
208                    schema_version: 1,
209                    wasm_api_version: None,
210                    published_at: t0,
211                }],
212            ),
213            (
214                "ext2",
215                vec![NewExtensionVersion {
216                    name: "Extension Two".into(),
217                    version: semver::Version::parse("0.1.0").unwrap(),
218                    description: "an old extension".into(),
219                    authors: vec!["marshall".into()],
220                    repository: "ext2/repo".into(),
221                    schema_version: 0,
222                    wasm_api_version: None,
223                    published_at: t0,
224                }],
225            ),
226        ]
227        .into_iter()
228        .collect(),
229    )
230    .await
231    .unwrap();
232
233    let versions = db.get_known_extension_versions().await.unwrap();
234    assert_eq!(
235        versions,
236        [
237            (
238                "ext1".into(),
239                vec!["0.0.1".into(), "0.0.2".into(), "0.0.3".into()]
240            ),
241            ("ext2".into(), vec!["0.1.0".into(), "0.2.0".into()])
242        ]
243        .into_iter()
244        .collect()
245    );
246
247    let extensions = db.get_extensions(None, 1, 5).await.unwrap();
248    assert_eq!(
249        extensions,
250        &[
251            ExtensionMetadata {
252                id: "ext2".into(),
253                manifest: rpc::ExtensionApiManifest {
254                    name: "Extension Two".into(),
255                    version: "0.2.0".into(),
256                    authors: vec!["marshall".into()],
257                    description: Some("a great extension".into()),
258                    repository: "ext2/repo".into(),
259                    schema_version: Some(0),
260                    wasm_api_version: None,
261                },
262                published_at: t0_chrono,
263                download_count: 7
264            },
265            ExtensionMetadata {
266                id: "ext1".into(),
267                manifest: rpc::ExtensionApiManifest {
268                    name: "Extension One".into(),
269                    version: "0.0.3".into(),
270                    authors: vec!["max".into(), "marshall".into()],
271                    description: Some("a real good extension".into()),
272                    repository: "ext1/repo".into(),
273                    schema_version: Some(1),
274                    wasm_api_version: None,
275                },
276                published_at: t0_chrono,
277                download_count: 5,
278            },
279        ]
280    );
281}
282
283test_both_dbs!(
284    test_extensions_by_id,
285    test_extensions_by_id_postgres,
286    test_extensions_by_id_sqlite
287);
288
289async fn test_extensions_by_id(db: &Arc<Database>) {
290    let versions = db.get_known_extension_versions().await.unwrap();
291    assert!(versions.is_empty());
292
293    let extensions = db.get_extensions(None, 1, 5).await.unwrap();
294    assert!(extensions.is_empty());
295
296    let t0 = time::OffsetDateTime::from_unix_timestamp_nanos(0).unwrap();
297    let t0 = time::PrimitiveDateTime::new(t0.date(), t0.time());
298
299    let t0_chrono = convert_time_to_chrono(t0);
300
301    db.insert_extension_versions(
302        &[
303            (
304                "ext1",
305                vec![
306                    NewExtensionVersion {
307                        name: "Extension 1".into(),
308                        version: semver::Version::parse("0.0.1").unwrap(),
309                        description: "an extension".into(),
310                        authors: vec!["max".into()],
311                        repository: "ext1/repo".into(),
312                        schema_version: 1,
313                        wasm_api_version: Some("0.0.4".into()),
314                        published_at: t0,
315                    },
316                    NewExtensionVersion {
317                        name: "Extension 1".into(),
318                        version: semver::Version::parse("0.0.2").unwrap(),
319                        description: "a good extension".into(),
320                        authors: vec!["max".into()],
321                        repository: "ext1/repo".into(),
322                        schema_version: 1,
323                        wasm_api_version: Some("0.0.4".into()),
324                        published_at: t0,
325                    },
326                    NewExtensionVersion {
327                        name: "Extension 1".into(),
328                        version: semver::Version::parse("0.0.3").unwrap(),
329                        description: "a real good extension".into(),
330                        authors: vec!["max".into(), "marshall".into()],
331                        repository: "ext1/repo".into(),
332                        schema_version: 1,
333                        wasm_api_version: Some("0.0.5".into()),
334                        published_at: t0,
335                    },
336                ],
337            ),
338            (
339                "ext2",
340                vec![NewExtensionVersion {
341                    name: "Extension 2".into(),
342                    version: semver::Version::parse("0.2.0").unwrap(),
343                    description: "a great extension".into(),
344                    authors: vec!["marshall".into()],
345                    repository: "ext2/repo".into(),
346                    schema_version: 0,
347                    wasm_api_version: None,
348                    published_at: t0,
349                }],
350            ),
351        ]
352        .into_iter()
353        .collect(),
354    )
355    .await
356    .unwrap();
357
358    let extensions = db
359        .get_extensions_by_ids(
360            &["ext1"],
361            Some(&ExtensionVersionConstraints {
362                schema_versions: 1..=1,
363                wasm_api_versions: "0.0.1".parse().unwrap()..="0.0.4".parse().unwrap(),
364            }),
365        )
366        .await
367        .unwrap();
368
369    assert_eq!(
370        extensions,
371        &[ExtensionMetadata {
372            id: "ext1".into(),
373            manifest: rpc::ExtensionApiManifest {
374                name: "Extension 1".into(),
375                version: "0.0.2".into(),
376                authors: vec!["max".into()],
377                description: Some("a good extension".into()),
378                repository: "ext1/repo".into(),
379                schema_version: Some(1),
380                wasm_api_version: Some("0.0.4".into()),
381            },
382            published_at: t0_chrono,
383            download_count: 0,
384        }]
385    );
386}