]> Untitled Git - lemmy.git/blob - crates/db_schema/src/aggregates/site_aggregates.rs
Cache & Optimize Woodpecker CI (#3450)
[lemmy.git] / crates / db_schema / src / aggregates / site_aggregates.rs
1 use crate::{
2   aggregates::structs::SiteAggregates,
3   schema::site_aggregates,
4   utils::{get_conn, DbPool},
5 };
6 use diesel::result::Error;
7 use diesel_async::RunQueryDsl;
8
9 impl SiteAggregates {
10   pub async fn read(pool: &mut DbPool<'_>) -> Result<Self, Error> {
11     let conn = &mut get_conn(pool).await?;
12     site_aggregates::table.first::<Self>(conn).await
13   }
14 }
15
16 #[cfg(test)]
17 mod tests {
18   #![allow(clippy::unwrap_used)]
19   #![allow(clippy::indexing_slicing)]
20
21   use crate::{
22     aggregates::site_aggregates::SiteAggregates,
23     source::{
24       comment::{Comment, CommentInsertForm},
25       community::{Community, CommunityInsertForm, CommunityUpdateForm},
26       instance::Instance,
27       person::{Person, PersonInsertForm},
28       post::{Post, PostInsertForm},
29       site::{Site, SiteInsertForm},
30     },
31     traits::Crud,
32     utils::{build_db_pool_for_tests, DbPool},
33   };
34   use serial_test::serial;
35
36   async fn prepare_site_with_community(
37     pool: &mut DbPool<'_>,
38   ) -> (Instance, Person, Site, Community) {
39     let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string())
40       .await
41       .unwrap();
42
43     let new_person = PersonInsertForm::builder()
44       .name("thommy_site_agg".into())
45       .public_key("pubkey".to_string())
46       .instance_id(inserted_instance.id)
47       .build();
48
49     let inserted_person = Person::create(pool, &new_person).await.unwrap();
50
51     let site_form = SiteInsertForm::builder()
52       .name("test_site".into())
53       .instance_id(inserted_instance.id)
54       .build();
55
56     let inserted_site = Site::create(pool, &site_form).await.unwrap();
57
58     let new_community = CommunityInsertForm::builder()
59       .name("TIL_site_agg".into())
60       .title("nada".to_owned())
61       .public_key("pubkey".to_string())
62       .instance_id(inserted_instance.id)
63       .build();
64
65     let inserted_community = Community::create(pool, &new_community).await.unwrap();
66     (
67       inserted_instance,
68       inserted_person,
69       inserted_site,
70       inserted_community,
71     )
72   }
73
74   #[tokio::test]
75   #[serial]
76   async fn test_crud() {
77     let pool = &build_db_pool_for_tests().await;
78     let pool = &mut pool.into();
79
80     let (inserted_instance, inserted_person, inserted_site, inserted_community) =
81       prepare_site_with_community(pool).await;
82
83     let new_post = PostInsertForm::builder()
84       .name("A test post".into())
85       .creator_id(inserted_person.id)
86       .community_id(inserted_community.id)
87       .build();
88
89     // Insert two of those posts
90     let inserted_post = Post::create(pool, &new_post).await.unwrap();
91     let _inserted_post_again = Post::create(pool, &new_post).await.unwrap();
92
93     let comment_form = CommentInsertForm::builder()
94       .content("A test comment".into())
95       .creator_id(inserted_person.id)
96       .post_id(inserted_post.id)
97       .build();
98
99     // Insert two of those comments
100     let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
101
102     let child_comment_form = CommentInsertForm::builder()
103       .content("A test comment".into())
104       .creator_id(inserted_person.id)
105       .post_id(inserted_post.id)
106       .build();
107
108     let _inserted_child_comment =
109       Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
110         .await
111         .unwrap();
112
113     let site_aggregates_before_delete = SiteAggregates::read(pool).await.unwrap();
114
115     // TODO: this is unstable, sometimes it returns 0 users, sometimes 1
116     //assert_eq!(0, site_aggregates_before_delete.users);
117     assert_eq!(1, site_aggregates_before_delete.communities);
118     assert_eq!(2, site_aggregates_before_delete.posts);
119     assert_eq!(2, site_aggregates_before_delete.comments);
120
121     // Try a post delete
122     Post::delete(pool, inserted_post.id).await.unwrap();
123     let site_aggregates_after_post_delete = SiteAggregates::read(pool).await.unwrap();
124     assert_eq!(1, site_aggregates_after_post_delete.posts);
125     assert_eq!(0, site_aggregates_after_post_delete.comments);
126
127     // This shouuld delete all the associated rows, and fire triggers
128     let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
129     assert_eq!(1, person_num_deleted);
130
131     // Delete the community
132     let community_num_deleted = Community::delete(pool, inserted_community.id)
133       .await
134       .unwrap();
135     assert_eq!(1, community_num_deleted);
136
137     // Site should still exist, it can without a site creator.
138     let after_delete_creator = SiteAggregates::read(pool).await;
139     assert!(after_delete_creator.is_ok());
140
141     Site::delete(pool, inserted_site.id).await.unwrap();
142     let after_delete_site = SiteAggregates::read(pool).await;
143     assert!(after_delete_site.is_err());
144
145     Instance::delete(pool, inserted_instance.id).await.unwrap();
146   }
147
148   #[tokio::test]
149   #[serial]
150   async fn test_soft_delete() {
151     let pool = &build_db_pool_for_tests().await;
152     let pool = &mut pool.into();
153
154     let (inserted_instance, inserted_person, inserted_site, inserted_community) =
155       prepare_site_with_community(pool).await;
156
157     let site_aggregates_before = SiteAggregates::read(pool).await.unwrap();
158     assert_eq!(1, site_aggregates_before.communities);
159
160     Community::update(
161       pool,
162       inserted_community.id,
163       &CommunityUpdateForm::builder().deleted(Some(true)).build(),
164     )
165     .await
166     .unwrap();
167
168     let site_aggregates_after_delete = SiteAggregates::read(pool).await.unwrap();
169     assert_eq!(0, site_aggregates_after_delete.communities);
170
171     Community::update(
172       pool,
173       inserted_community.id,
174       &CommunityUpdateForm::builder().deleted(Some(false)).build(),
175     )
176     .await
177     .unwrap();
178
179     Community::update(
180       pool,
181       inserted_community.id,
182       &CommunityUpdateForm::builder().removed(Some(true)).build(),
183     )
184     .await
185     .unwrap();
186
187     let site_aggregates_after_remove = SiteAggregates::read(pool).await.unwrap();
188     assert_eq!(0, site_aggregates_after_remove.communities);
189
190     Community::update(
191       pool,
192       inserted_community.id,
193       &CommunityUpdateForm::builder().deleted(Some(true)).build(),
194     )
195     .await
196     .unwrap();
197
198     let site_aggregates_after_remove_delete = SiteAggregates::read(pool).await.unwrap();
199     assert_eq!(0, site_aggregates_after_remove_delete.communities);
200
201     Community::delete(pool, inserted_community.id)
202       .await
203       .unwrap();
204     Site::delete(pool, inserted_site.id).await.unwrap();
205     Person::delete(pool, inserted_person.id).await.unwrap();
206     Instance::delete(pool, inserted_instance.id).await.unwrap();
207   }
208 }