1use super::Database;
2use crate::{
3 db::{ExtensionMetadata, NewExtensionVersion},
4 test_both_dbs,
5};
6use std::sync::Arc;
7use time::{OffsetDateTime, PrimitiveDateTime};
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, 5).await.unwrap();
20 assert!(extensions.is_empty());
21
22 let t0 = OffsetDateTime::from_unix_timestamp_nanos(0).unwrap();
23 let t0 = PrimitiveDateTime::new(t0.date(), t0.time());
24
25 db.insert_extension_versions(
26 &[
27 (
28 "ext1",
29 vec![
30 NewExtensionVersion {
31 name: "Extension 1".into(),
32 version: semver::Version::parse("0.0.1").unwrap(),
33 description: "an extension".into(),
34 authors: vec!["max".into()],
35 repository: "ext1/repo".into(),
36 published_at: t0,
37 },
38 NewExtensionVersion {
39 name: "Extension One".into(),
40 version: semver::Version::parse("0.0.2").unwrap(),
41 description: "a good extension".into(),
42 authors: vec!["max".into(), "marshall".into()],
43 repository: "ext1/repo".into(),
44 published_at: t0,
45 },
46 ],
47 ),
48 (
49 "ext2",
50 vec![NewExtensionVersion {
51 name: "Extension Two".into(),
52 version: semver::Version::parse("0.2.0").unwrap(),
53 description: "a great extension".into(),
54 authors: vec!["marshall".into()],
55 repository: "ext2/repo".into(),
56 published_at: t0,
57 }],
58 ),
59 ]
60 .into_iter()
61 .collect(),
62 )
63 .await
64 .unwrap();
65
66 let versions = db.get_known_extension_versions().await.unwrap();
67 assert_eq!(
68 versions,
69 [
70 ("ext1".into(), vec!["0.0.1".into(), "0.0.2".into()]),
71 ("ext2".into(), vec!["0.2.0".into()])
72 ]
73 .into_iter()
74 .collect()
75 );
76
77 // The latest version of each extension is returned.
78 let extensions = db.get_extensions(None, 5).await.unwrap();
79 assert_eq!(
80 extensions,
81 &[
82 ExtensionMetadata {
83 id: "ext1".into(),
84 name: "Extension One".into(),
85 version: "0.0.2".into(),
86 authors: vec!["max".into(), "marshall".into()],
87 description: "a good extension".into(),
88 repository: "ext1/repo".into(),
89 published_at: t0,
90 download_count: 0,
91 },
92 ExtensionMetadata {
93 id: "ext2".into(),
94 name: "Extension Two".into(),
95 version: "0.2.0".into(),
96 authors: vec!["marshall".into()],
97 description: "a great extension".into(),
98 repository: "ext2/repo".into(),
99 published_at: t0,
100 download_count: 0
101 },
102 ]
103 );
104
105 // Record extensions being downloaded.
106 for _ in 0..7 {
107 assert!(db.record_extension_download("ext2", "0.0.2").await.unwrap());
108 }
109
110 for _ in 0..3 {
111 assert!(db.record_extension_download("ext1", "0.0.1").await.unwrap());
112 }
113
114 for _ in 0..2 {
115 assert!(db.record_extension_download("ext1", "0.0.2").await.unwrap());
116 }
117
118 // Record download returns false if the extension does not exist.
119 assert!(!db
120 .record_extension_download("no-such-extension", "0.0.2")
121 .await
122 .unwrap());
123
124 // Extensions are returned in descending order of total downloads.
125 let extensions = db.get_extensions(None, 5).await.unwrap();
126 assert_eq!(
127 extensions,
128 &[
129 ExtensionMetadata {
130 id: "ext2".into(),
131 name: "Extension Two".into(),
132 version: "0.2.0".into(),
133 authors: vec!["marshall".into()],
134 description: "a great extension".into(),
135 repository: "ext2/repo".into(),
136 published_at: t0,
137 download_count: 7
138 },
139 ExtensionMetadata {
140 id: "ext1".into(),
141 name: "Extension One".into(),
142 version: "0.0.2".into(),
143 authors: vec!["max".into(), "marshall".into()],
144 description: "a good extension".into(),
145 repository: "ext1/repo".into(),
146 published_at: t0,
147 download_count: 5,
148 },
149 ]
150 );
151
152 // Add more extensions, including a new version of `ext1`, and backfilling
153 // an older version of `ext2`.
154 db.insert_extension_versions(
155 &[
156 (
157 "ext1",
158 vec![NewExtensionVersion {
159 name: "Extension One".into(),
160 version: semver::Version::parse("0.0.3").unwrap(),
161 description: "a real good extension".into(),
162 authors: vec!["max".into(), "marshall".into()],
163 repository: "ext1/repo".into(),
164 published_at: t0,
165 }],
166 ),
167 (
168 "ext2",
169 vec![NewExtensionVersion {
170 name: "Extension Two".into(),
171 version: semver::Version::parse("0.1.0").unwrap(),
172 description: "an old extension".into(),
173 authors: vec!["marshall".into()],
174 repository: "ext2/repo".into(),
175 published_at: t0,
176 }],
177 ),
178 ]
179 .into_iter()
180 .collect(),
181 )
182 .await
183 .unwrap();
184
185 let versions = db.get_known_extension_versions().await.unwrap();
186 assert_eq!(
187 versions,
188 [
189 (
190 "ext1".into(),
191 vec!["0.0.1".into(), "0.0.2".into(), "0.0.3".into()]
192 ),
193 ("ext2".into(), vec!["0.1.0".into(), "0.2.0".into()])
194 ]
195 .into_iter()
196 .collect()
197 );
198
199 let extensions = db.get_extensions(None, 5).await.unwrap();
200 assert_eq!(
201 extensions,
202 &[
203 ExtensionMetadata {
204 id: "ext2".into(),
205 name: "Extension Two".into(),
206 version: "0.2.0".into(),
207 authors: vec!["marshall".into()],
208 description: "a great extension".into(),
209 repository: "ext2/repo".into(),
210 published_at: t0,
211 download_count: 7
212 },
213 ExtensionMetadata {
214 id: "ext1".into(),
215 name: "Extension One".into(),
216 version: "0.0.3".into(),
217 authors: vec!["max".into(), "marshall".into()],
218 description: "a real good extension".into(),
219 repository: "ext1/repo".into(),
220 published_at: t0,
221 download_count: 5,
222 },
223 ]
224 );
225}