flix_db/entity/content/
mod.rs

1//! This module contains entities for storing media file information
2
3pub mod libraries;
4
5pub mod collections;
6
7pub mod movies;
8
9pub mod episodes;
10pub mod seasons;
11pub mod shows;
12
13#[cfg(test)]
14mod tests {
15	use std::path::Path;
16
17	use flix_model::id::{CollectionId, LibraryId, MovieId, ShowId};
18
19	use sea_orm::ActiveModelTrait;
20	use sea_orm::ActiveValue::{NotSet, Set};
21	use sea_orm::sqlx::error::ErrorKind;
22	use sea_orm_migration::MigratorTrait;
23
24	use crate::migration::Migrator;
25	use crate::tests::new_memory_db;
26
27	use super::super::tests::get_error_kind;
28	use super::super::tests::{
29		make_flix_collection, make_flix_episode, make_flix_movie, make_flix_season, make_flix_show,
30	};
31	use super::super::tests::{noneable, notsettable};
32
33	#[tokio::test]
34	async fn test_inserts() {
35		let db = new_memory_db().await;
36		Migrator::up(&db, None).await.expect("up");
37
38		// Libraries
39		macro_rules! assert_library {
40			($db:expr, $id:literal, Success $(; $($skip:ident),+)?) => {
41				let model = assert_library!(@insert, $db, $id $(; $($skip),+)?)
42					.expect("insert");
43
44				assert_eq!(model.id, LibraryId::from_raw($id));
45				assert_eq!(model.directory, Path::new(concat!("/L/", $id)).to_owned().into());
46			};
47			($db:expr, $id:literal, $error:ident $(; $($skip:ident),+)?) => {
48				let model = assert_library!(@insert, $db, $id $(; $($skip),+)?)
49					.expect_err("insert");
50
51				assert_eq!(get_error_kind(model).expect("get_error_kind"), ErrorKind::$error);
52			};
53			(@insert, $db:expr, $id:literal $(; $($skip:ident),+)?) => {
54				super::libraries::ActiveModel {
55					id: notsettable!(id, LibraryId::from_raw($id) $(, $($skip),+)?),
56					directory: notsettable!(directory, Path::new(concat!("/L/", $id)).to_owned().into() $(, $($skip),+)?),
57				}.insert($db).await
58			};
59		}
60		assert_library!(&db, 1, Success);
61		assert_library!(&db, 1, UniqueViolation);
62		assert_library!(&db, 2, Success);
63		assert_library!(&db, 3, Success; id);
64		assert_library!(&db, 4, NotNullViolation; directory);
65
66		// Collections
67		macro_rules! assert_collection {
68			($db:expr, $id:literal, $pid:expr, $lid:literal, Success $(; $($skip:ident),+)?) => {
69				let model = assert_collection!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
70					.expect("insert");
71
72				assert_eq!(model.id, CollectionId::from_raw($id));
73				assert_eq!(model.parent, $pid);
74				assert_eq!(model.slug, concat!("C/", $id).to_string());
75				assert_eq!(model.library, LibraryId::from_raw($lid));
76				assert_eq!(model.directory, Path::new(concat!("/C/", $id)).to_owned().into());
77				assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, Path::new(concat!("C/Poster", $id)).to_owned().into() $(, $($skip),+)?));
78			};
79			($db:expr, $id:literal, $pid:expr, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
80				let model = assert_collection!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
81					.expect_err("insert");
82
83				assert_eq!(get_error_kind(model).expect("get_error_kind"), ErrorKind::$error);
84			};
85			(@insert, $db:expr, $id:literal, $pid:expr, $lid:literal $(; $($skip:ident),+)?) => {
86				super::collections::ActiveModel {
87					id: notsettable!(id, CollectionId::from_raw($id) $(, $($skip),+)?),
88					parent: notsettable!(parent, $pid $(, $($skip),+)?),
89					slug: notsettable!(slug, concat!("C/", $id).to_string() $(, $($skip),+)?),
90					library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
91					directory: notsettable!(directory, Path::new(concat!("/C/", $id)).to_owned().into() $(, $($skip),+)?),
92					relative_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("C/Poster", $id)).to_owned().into()) $(, $($skip),+)?),
93				}.insert($db).await
94			};
95		}
96		assert_collection!(&db, 1, None, 0, ForeignKeyViolation);
97		assert_collection!(
98			&db,
99			1,
100			Some(CollectionId::from_raw(0)),
101			1,
102			ForeignKeyViolation
103		);
104		assert_collection!(&db, 1, None, 1, ForeignKeyViolation);
105		make_flix_collection!(&db, 1);
106		make_flix_collection!(&db, 2);
107		make_flix_collection!(&db, 3);
108		make_flix_collection!(&db, 4);
109		make_flix_collection!(&db, 8);
110
111		assert_collection!(&db, 1, None, 1, Success);
112		assert_collection!(&db, 1, None, 1, UniqueViolation);
113		assert_collection!(&db, 2, None, 1, Success);
114		assert_collection!(&db, 3, None, 1, Success; id);
115		assert_collection!(&db, 4, None, 1, Success; parent);
116		assert_collection!(&db, 5, None, 1, NotNullViolation; slug);
117		assert_collection!(&db, 6, None, 1, NotNullViolation; library);
118		assert_collection!(&db, 7, None, 1, NotNullViolation; directory);
119		assert_collection!(&db, 8, None, 1, Success; relative_poster_path);
120
121		// Movies
122		macro_rules! assert_movie {
123			($db:expr, $id:literal, $pid:expr, $lid:literal, Success $(; $($skip:ident),+)?) => {
124				let model = assert_movie!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
125					.expect("insert");
126
127				assert_eq!(model.id, MovieId::from_raw($id));
128				assert_eq!(model.parent, $pid);
129				assert_eq!(model.slug, concat!("M/", $id).to_string());
130				assert_eq!(model.library, LibraryId::from_raw($lid));
131				assert_eq!(model.directory, Path::new(concat!("/M/", $id)).to_owned().into());
132				assert_eq!(model.relative_media_path, Path::new(concat!("M/Media", $id)).to_owned().into());
133				assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, Path::new(concat!("M/Poster", $id)).to_owned().into() $(, $($skip),+)?));
134			};
135			($db:expr, $id:literal, $pid:expr, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
136				let model = assert_movie!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
137					.expect_err("insert");
138
139				assert_eq!(get_error_kind(model).expect("get_error_kind"), ErrorKind::$error);
140			};
141			(@insert, $db:expr, $id:literal, $pid:expr, $lid:literal $(; $($skip:ident),+)?) => {
142				super::movies::ActiveModel {
143					id: notsettable!(id, MovieId::from_raw($id) $(, $($skip),+)?),
144					parent: notsettable!(parent, $pid $(, $($skip),+)?),
145					slug: notsettable!(slug, concat!("M/", $id).to_string() $(, $($skip),+)?),
146					library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
147					directory: notsettable!(directory, Path::new(concat!("/M/", $id)).to_owned().into() $(, $($skip),+)?),
148					relative_media_path: notsettable!(relative_media_path, Path::new(concat!("M/Media", $id)).to_owned().into() $(, $($skip),+)?),
149					relative_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("M/Poster", $id)).to_owned().into()) $(, $($skip),+)?),
150				}.insert($db).await
151			};
152		}
153		assert_movie!(&db, 1, None, 0, ForeignKeyViolation);
154		assert_movie!(
155			&db,
156			1,
157			Some(CollectionId::from_raw(0)),
158			1,
159			ForeignKeyViolation
160		);
161		assert_movie!(&db, 1, None, 1, ForeignKeyViolation);
162		make_flix_movie!(&db, 1);
163		make_flix_movie!(&db, 2);
164		make_flix_movie!(&db, 3);
165		make_flix_movie!(&db, 4);
166		make_flix_movie!(&db, 9);
167
168		assert_movie!(&db, 1, None, 1, Success);
169		assert_movie!(&db, 1, None, 1, UniqueViolation);
170		assert_movie!(&db, 2, None, 1, Success);
171		assert_movie!(&db, 3, None, 1, Success; id);
172		assert_movie!(&db, 4, None, 1, Success; parent);
173		assert_movie!(&db, 5, None, 1, NotNullViolation; slug);
174		assert_movie!(&db, 6, None, 1, NotNullViolation; library);
175		assert_movie!(&db, 7, None, 1, NotNullViolation; directory);
176		assert_movie!(&db, 8, None, 1, NotNullViolation; relative_media_path);
177		assert_movie!(&db, 9, None, 1, Success; relative_poster_path);
178
179		// Shows
180		macro_rules! assert_show {
181			($db:expr, $id:literal, $pid:expr, $lid:literal, Success $(; $($skip:ident),+)?) => {
182				let model = assert_show!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
183					.expect("insert");
184
185				assert_eq!(model.id, ShowId::from_raw($id));
186				assert_eq!(model.parent, $pid);
187				assert_eq!(model.slug, concat!("S/", $id).to_string());
188				assert_eq!(model.library, LibraryId::from_raw($lid));
189				assert_eq!(model.directory, Path::new(concat!("/S/", $id)).to_owned().into());
190				assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, Path::new(concat!("S/Poster", $id)).to_owned().into() $(, $($skip),+)?));
191			};
192			($db:expr, $id:literal, $pid:expr, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
193				let model = assert_show!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
194					.expect_err("insert");
195
196				assert_eq!(get_error_kind(model).expect("get_error_kind"), ErrorKind::$error);
197			};
198			(@insert, $db:expr, $id:literal, $pid:expr, $lid:literal $(; $($skip:ident),+)?) => {
199				super::shows::ActiveModel {
200					id: notsettable!(id, ShowId::from_raw($id) $(, $($skip),+)?),
201					parent: notsettable!(parent, $pid $(, $($skip),+)?),
202					slug: notsettable!(slug, concat!("S/", $id).to_string() $(, $($skip),+)?),
203					library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
204					directory: notsettable!(directory, Path::new(concat!("/S/", $id)).to_owned().into() $(, $($skip),+)?),
205					relative_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("S/Poster", $id)).to_owned().into()) $(, $($skip),+)?),
206				}.insert($db).await
207			};
208		}
209		assert_show!(&db, 1, None, 0, ForeignKeyViolation);
210		assert_show!(
211			&db,
212			1,
213			Some(CollectionId::from_raw(0)),
214			1,
215			ForeignKeyViolation
216		);
217		assert_show!(&db, 1, None, 1, ForeignKeyViolation);
218		make_flix_show!(&db, 1);
219		make_flix_show!(&db, 2);
220		make_flix_show!(&db, 3);
221		make_flix_show!(&db, 4);
222		make_flix_show!(&db, 8);
223
224		assert_show!(&db, 1, None, 1, Success);
225		assert_show!(&db, 1, None, 1, UniqueViolation);
226		assert_show!(&db, 2, None, 1, Success);
227		assert_show!(&db, 3, None, 1, Success; id);
228		assert_show!(&db, 4, None, 1, Success; parent);
229		assert_show!(&db, 5, None, 1, NotNullViolation; slug);
230		assert_show!(&db, 6, None, 1, NotNullViolation; library);
231		assert_show!(&db, 7, None, 1, NotNullViolation; directory);
232		assert_show!(&db, 8, None, 1, Success; relative_poster_path);
233
234		// Seasons
235		macro_rules! assert_season {
236			($db:expr, $id:literal, $season:literal, $lid:literal, Success $(; $($skip:ident),+)?) => {
237				let model = assert_season!(@insert, $db, $id, $season, $lid $(; $($skip),+)?)
238					.expect("insert");
239
240				assert_eq!(model.show, ShowId::from_raw($id));
241				assert_eq!(model.season, $season);
242				assert_eq!(model.slug, concat!("S/S", $id).to_string());
243				assert_eq!(model.library, LibraryId::from_raw($lid));
244				assert_eq!(model.directory, Path::new(concat!("/S/S", $id)).to_owned().into());
245				assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, Path::new(concat!("S/S/Poster", $id)).to_owned().into() $(, $($skip),+)?));
246			};
247			($db:expr, $id:literal, $season:literal, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
248				let model = assert_season!(@insert, $db, $id, $season, $lid $(; $($skip),+)?)
249					.expect_err("insert");
250
251				assert_eq!(get_error_kind(model).expect("get_error_kind"), ErrorKind::$error);
252			};
253			(@insert, $db:expr, $id:literal, $season:literal, $lid:literal $(; $($skip:ident),+)?) => {
254				super::seasons::ActiveModel {
255					show: notsettable!(id, ShowId::from_raw($id) $(, $($skip),+)?),
256					season: notsettable!(season, $season $(, $($skip),+)?),
257					slug: notsettable!(slug, concat!("S/S", $id).to_string() $(, $($skip),+)?),
258					library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
259					directory: notsettable!(directory, Path::new(concat!("/S/S", $id)).to_owned().into() $(, $($skip),+)?),
260					relative_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("S/S/Poster", $id)).to_owned().into()) $(, $($skip),+)?),
261				}.insert($db).await
262			};
263		}
264		assert_season!(&db, 1, 1, 0, ForeignKeyViolation);
265		assert_season!(&db, 1, 1, 1, ForeignKeyViolation);
266		make_flix_season!(&db, 1, 1);
267		make_flix_season!(&db, 1, 2);
268		make_flix_season!(&db, 2, 1);
269		make_flix_season!(&db, 3, 1);
270		make_flix_season!(&db, 8, 1);
271
272		assert_season!(&db, 1, 1, 1, Success);
273		assert_season!(&db, 1, 2, 1, Success);
274		assert_season!(&db, 1, 1, 1, UniqueViolation);
275		assert_season!(&db, 2, 1, 1, Success);
276		assert_season!(&db, 3, 1, 1, Success; show);
277		assert_season!(&db, 4, 1, 1, NotNullViolation; season);
278		assert_season!(&db, 5, 1, 1, NotNullViolation; slug);
279		assert_season!(&db, 6, 1, 1, NotNullViolation; library);
280		assert_season!(&db, 7, 1, 1, NotNullViolation; directory);
281		assert_season!(&db, 8, 1, 1, Success; relative_poster_path);
282
283		// Episodes
284		macro_rules! assert_episode {
285			($db:expr, $id:literal, $season:literal, $episode:literal, $lid:literal, Success $(; $($skip:ident),+)?) => {
286				let model = assert_episode!(@insert, $db, $id, $season, $episode, $lid $(; $($skip),+)?)
287					.expect("insert");
288
289				assert_eq!(model.show, ShowId::from_raw($id));
290				assert_eq!(model.season, $season);
291				assert_eq!(model.episode, $episode);
292				assert_eq!(model.slug, concat!("S/S/E", $id).to_string());
293				assert_eq!(model.library, LibraryId::from_raw($lid));
294				assert_eq!(model.directory, Path::new(concat!("/S/S/E", $id)).to_owned().into());
295				assert_eq!(model.relative_media_path, Path::new(concat!("E/Media", $id)).to_owned().into());
296				assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, Path::new(concat!("S/S/E/Poster", $id)).to_owned().into() $(, $($skip),+)?));
297			};
298			($db:expr, $id:literal, $season:literal, $episode:literal, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
299				let model = assert_episode!(@insert, $db, $id, $season, $episode, $lid $(; $($skip),+)?)
300					.expect_err("insert");
301
302				assert_eq!(get_error_kind(model).expect("get_error_kind"), ErrorKind::$error);
303			};
304			(@insert, $db:expr, $id:literal, $season:literal, $episode:literal, $lid:literal $(; $($skip:ident),+)?) => {
305				super::episodes::ActiveModel {
306					show: notsettable!(id, ShowId::from_raw($id) $(, $($skip),+)?),
307					season: notsettable!(season, $season $(, $($skip),+)?),
308					episode: notsettable!(episode, $episode $(, $($skip),+)?),
309					slug: notsettable!(slug, concat!("S/S/E", $id).to_string() $(, $($skip),+)?),
310					library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
311					directory: notsettable!(directory, Path::new(concat!("/S/S/E", $id)).to_owned().into() $(, $($skip),+)?),
312					relative_media_path: notsettable!(relative_media_path, Path::new(concat!("E/Media", $id)).to_owned().into() $(, $($skip),+)?),
313					relative_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("S/S/E/Poster", $id)).to_owned().into()) $(, $($skip),+)?),
314				}.insert($db).await
315			};
316		}
317		assert_episode!(&db, 1, 1, 1, 0, ForeignKeyViolation);
318		assert_episode!(&db, 1, 1, 1, 1, ForeignKeyViolation);
319		make_flix_episode!(&db, 1, 1, 1);
320		make_flix_episode!(&db, 1, 1, 2);
321		make_flix_episode!(&db, 2, 1, 1);
322		make_flix_episode!(&db, 3, 1, 1);
323		make_flix_show!(&db, 10);
324		make_flix_season!(&db, 10, 1);
325		make_flix_episode!(&db, 10, 1, 1);
326
327		assert_episode!(&db, 1, 1, 1, 1, Success);
328		assert_episode!(&db, 1, 1, 2, 1, Success);
329		assert_episode!(&db, 1, 1, 1, 1, UniqueViolation);
330		assert_episode!(&db, 2, 1, 1, 1, Success);
331		assert_episode!(&db, 3, 1, 1, 1, Success; show);
332		assert_episode!(&db, 4, 1, 1, 1, NotNullViolation; season);
333		assert_episode!(&db, 5, 1, 1, 1, NotNullViolation; episode);
334		assert_episode!(&db, 6, 1, 1, 1, NotNullViolation; slug);
335		assert_episode!(&db, 7, 1, 1, 1, NotNullViolation; library);
336		assert_episode!(&db, 8, 1, 1, 1, NotNullViolation; directory);
337		assert_episode!(&db, 9, 1, 1, 1, NotNullViolation; relative_media_path);
338		assert_episode!(&db, 10, 1, 1, 1, Success; relative_poster_path);
339	}
340}