tests.rs

  1use super::*;
  2use gpui::executor::{Background, Deterministic};
  3use std::sync::Arc;
  4
  5macro_rules! test_both_dbs {
  6    ($postgres_test_name:ident, $sqlite_test_name:ident, $db:ident, $body:block) => {
  7        #[gpui::test]
  8        async fn $postgres_test_name() {
  9            let test_db = TestDb::postgres(Deterministic::new(0).build_background());
 10            let $db = test_db.db();
 11            $body
 12        }
 13
 14        #[gpui::test]
 15        async fn $sqlite_test_name() {
 16            let test_db = TestDb::sqlite(Deterministic::new(0).build_background());
 17            let $db = test_db.db();
 18            $body
 19        }
 20    };
 21}
 22
 23test_both_dbs!(
 24    test_get_users_by_ids_postgres,
 25    test_get_users_by_ids_sqlite,
 26    db,
 27    {
 28        let mut user_ids = Vec::new();
 29        let mut user_metric_ids = Vec::new();
 30        for i in 1..=4 {
 31            let user = db
 32                .create_user(
 33                    &format!("user{i}@example.com"),
 34                    false,
 35                    NewUserParams {
 36                        github_login: format!("user{i}"),
 37                        github_user_id: i,
 38                        invite_count: 0,
 39                    },
 40                )
 41                .await
 42                .unwrap();
 43            user_ids.push(user.user_id);
 44            user_metric_ids.push(user.metrics_id);
 45        }
 46
 47        assert_eq!(
 48            db.get_users_by_ids(user_ids.clone()).await.unwrap(),
 49            vec![
 50                User {
 51                    id: user_ids[0],
 52                    github_login: "user1".to_string(),
 53                    github_user_id: Some(1),
 54                    email_address: Some("user1@example.com".to_string()),
 55                    admin: false,
 56                    metrics_id: user_metric_ids[0].parse().unwrap(),
 57                    ..Default::default()
 58                },
 59                User {
 60                    id: user_ids[1],
 61                    github_login: "user2".to_string(),
 62                    github_user_id: Some(2),
 63                    email_address: Some("user2@example.com".to_string()),
 64                    admin: false,
 65                    metrics_id: user_metric_ids[1].parse().unwrap(),
 66                    ..Default::default()
 67                },
 68                User {
 69                    id: user_ids[2],
 70                    github_login: "user3".to_string(),
 71                    github_user_id: Some(3),
 72                    email_address: Some("user3@example.com".to_string()),
 73                    admin: false,
 74                    metrics_id: user_metric_ids[2].parse().unwrap(),
 75                    ..Default::default()
 76                },
 77                User {
 78                    id: user_ids[3],
 79                    github_login: "user4".to_string(),
 80                    github_user_id: Some(4),
 81                    email_address: Some("user4@example.com".to_string()),
 82                    admin: false,
 83                    metrics_id: user_metric_ids[3].parse().unwrap(),
 84                    ..Default::default()
 85                }
 86            ]
 87        );
 88    }
 89);
 90
 91test_both_dbs!(
 92    test_get_user_by_github_account_postgres,
 93    test_get_user_by_github_account_sqlite,
 94    db,
 95    {
 96        let user_id1 = db
 97            .create_user(
 98                "user1@example.com",
 99                false,
100                NewUserParams {
101                    github_login: "login1".into(),
102                    github_user_id: 101,
103                    invite_count: 0,
104                },
105            )
106            .await
107            .unwrap()
108            .user_id;
109        let user_id2 = db
110            .create_user(
111                "user2@example.com",
112                false,
113                NewUserParams {
114                    github_login: "login2".into(),
115                    github_user_id: 102,
116                    invite_count: 0,
117                },
118            )
119            .await
120            .unwrap()
121            .user_id;
122
123        let user = db
124            .get_user_by_github_account("login1", None)
125            .await
126            .unwrap()
127            .unwrap();
128        assert_eq!(user.id, user_id1);
129        assert_eq!(&user.github_login, "login1");
130        assert_eq!(user.github_user_id, Some(101));
131
132        assert!(db
133            .get_user_by_github_account("non-existent-login", None)
134            .await
135            .unwrap()
136            .is_none());
137
138        let user = db
139            .get_user_by_github_account("the-new-login2", Some(102))
140            .await
141            .unwrap()
142            .unwrap();
143        assert_eq!(user.id, user_id2);
144        assert_eq!(&user.github_login, "the-new-login2");
145        assert_eq!(user.github_user_id, Some(102));
146    }
147);
148
149test_both_dbs!(
150    test_create_access_tokens_postgres,
151    test_create_access_tokens_sqlite,
152    db,
153    {
154        let user = db
155            .create_user(
156                "u1@example.com",
157                false,
158                NewUserParams {
159                    github_login: "u1".into(),
160                    github_user_id: 1,
161                    invite_count: 0,
162                },
163            )
164            .await
165            .unwrap()
166            .user_id;
167
168        db.create_access_token_hash(user, "h1", 3).await.unwrap();
169        db.create_access_token_hash(user, "h2", 3).await.unwrap();
170        assert_eq!(
171            db.get_access_token_hashes(user).await.unwrap(),
172            &["h2".to_string(), "h1".to_string()]
173        );
174
175        db.create_access_token_hash(user, "h3", 3).await.unwrap();
176        assert_eq!(
177            db.get_access_token_hashes(user).await.unwrap(),
178            &["h3".to_string(), "h2".to_string(), "h1".to_string(),]
179        );
180
181        db.create_access_token_hash(user, "h4", 3).await.unwrap();
182        assert_eq!(
183            db.get_access_token_hashes(user).await.unwrap(),
184            &["h4".to_string(), "h3".to_string(), "h2".to_string(),]
185        );
186
187        db.create_access_token_hash(user, "h5", 3).await.unwrap();
188        assert_eq!(
189            db.get_access_token_hashes(user).await.unwrap(),
190            &["h5".to_string(), "h4".to_string(), "h3".to_string()]
191        );
192    }
193);
194
195test_both_dbs!(test_add_contacts_postgres, test_add_contacts_sqlite, db, {
196    let mut user_ids = Vec::new();
197    for i in 0..3 {
198        user_ids.push(
199            db.create_user(
200                &format!("user{i}@example.com"),
201                false,
202                NewUserParams {
203                    github_login: format!("user{i}"),
204                    github_user_id: i,
205                    invite_count: 0,
206                },
207            )
208            .await
209            .unwrap()
210            .user_id,
211        );
212    }
213
214    let user_1 = user_ids[0];
215    let user_2 = user_ids[1];
216    let user_3 = user_ids[2];
217
218    // User starts with no contacts
219    assert_eq!(db.get_contacts(user_1).await.unwrap(), &[]);
220
221    // User requests a contact. Both users see the pending request.
222    db.send_contact_request(user_1, user_2).await.unwrap();
223    assert!(!db.has_contact(user_1, user_2).await.unwrap());
224    assert!(!db.has_contact(user_2, user_1).await.unwrap());
225    assert_eq!(
226        db.get_contacts(user_1).await.unwrap(),
227        &[Contact::Outgoing { user_id: user_2 }],
228    );
229    assert_eq!(
230        db.get_contacts(user_2).await.unwrap(),
231        &[Contact::Incoming {
232            user_id: user_1,
233            should_notify: true
234        }]
235    );
236
237    // User 2 dismisses the contact request notification without accepting or rejecting.
238    // We shouldn't notify them again.
239    db.dismiss_contact_notification(user_1, user_2)
240        .await
241        .unwrap_err();
242    db.dismiss_contact_notification(user_2, user_1)
243        .await
244        .unwrap();
245    assert_eq!(
246        db.get_contacts(user_2).await.unwrap(),
247        &[Contact::Incoming {
248            user_id: user_1,
249            should_notify: false
250        }]
251    );
252
253    // User can't accept their own contact request
254    db.respond_to_contact_request(user_1, user_2, true)
255        .await
256        .unwrap_err();
257
258    // User accepts a contact request. Both users see the contact.
259    db.respond_to_contact_request(user_2, user_1, true)
260        .await
261        .unwrap();
262    assert_eq!(
263        db.get_contacts(user_1).await.unwrap(),
264        &[Contact::Accepted {
265            user_id: user_2,
266            should_notify: true,
267            busy: false,
268        }],
269    );
270    assert!(db.has_contact(user_1, user_2).await.unwrap());
271    assert!(db.has_contact(user_2, user_1).await.unwrap());
272    assert_eq!(
273        db.get_contacts(user_2).await.unwrap(),
274        &[Contact::Accepted {
275            user_id: user_1,
276            should_notify: false,
277            busy: false,
278        }]
279    );
280
281    // Users cannot re-request existing contacts.
282    db.send_contact_request(user_1, user_2).await.unwrap_err();
283    db.send_contact_request(user_2, user_1).await.unwrap_err();
284
285    // Users can't dismiss notifications of them accepting other users' requests.
286    db.dismiss_contact_notification(user_2, user_1)
287        .await
288        .unwrap_err();
289    assert_eq!(
290        db.get_contacts(user_1).await.unwrap(),
291        &[Contact::Accepted {
292            user_id: user_2,
293            should_notify: true,
294            busy: false,
295        }]
296    );
297
298    // Users can dismiss notifications of other users accepting their requests.
299    db.dismiss_contact_notification(user_1, user_2)
300        .await
301        .unwrap();
302    assert_eq!(
303        db.get_contacts(user_1).await.unwrap(),
304        &[Contact::Accepted {
305            user_id: user_2,
306            should_notify: false,
307            busy: false,
308        }]
309    );
310
311    // Users send each other concurrent contact requests and
312    // see that they are immediately accepted.
313    db.send_contact_request(user_1, user_3).await.unwrap();
314    db.send_contact_request(user_3, user_1).await.unwrap();
315    assert_eq!(
316        db.get_contacts(user_1).await.unwrap(),
317        &[
318            Contact::Accepted {
319                user_id: user_2,
320                should_notify: false,
321                busy: false,
322            },
323            Contact::Accepted {
324                user_id: user_3,
325                should_notify: false,
326                busy: false,
327            }
328        ]
329    );
330    assert_eq!(
331        db.get_contacts(user_3).await.unwrap(),
332        &[Contact::Accepted {
333            user_id: user_1,
334            should_notify: false,
335            busy: false,
336        }],
337    );
338
339    // User declines a contact request. Both users see that it is gone.
340    db.send_contact_request(user_2, user_3).await.unwrap();
341    db.respond_to_contact_request(user_3, user_2, false)
342        .await
343        .unwrap();
344    assert!(!db.has_contact(user_2, user_3).await.unwrap());
345    assert!(!db.has_contact(user_3, user_2).await.unwrap());
346    assert_eq!(
347        db.get_contacts(user_2).await.unwrap(),
348        &[Contact::Accepted {
349            user_id: user_1,
350            should_notify: false,
351            busy: false,
352        }]
353    );
354    assert_eq!(
355        db.get_contacts(user_3).await.unwrap(),
356        &[Contact::Accepted {
357            user_id: user_1,
358            should_notify: false,
359            busy: false,
360        }],
361    );
362});
363
364test_both_dbs!(test_metrics_id_postgres, test_metrics_id_sqlite, db, {
365    let NewUserResult {
366        user_id: user1,
367        metrics_id: metrics_id1,
368        ..
369    } = db
370        .create_user(
371            "person1@example.com",
372            false,
373            NewUserParams {
374                github_login: "person1".into(),
375                github_user_id: 101,
376                invite_count: 5,
377            },
378        )
379        .await
380        .unwrap();
381    let NewUserResult {
382        user_id: user2,
383        metrics_id: metrics_id2,
384        ..
385    } = db
386        .create_user(
387            "person2@example.com",
388            false,
389            NewUserParams {
390                github_login: "person2".into(),
391                github_user_id: 102,
392                invite_count: 5,
393            },
394        )
395        .await
396        .unwrap();
397
398    assert_eq!(db.get_user_metrics_id(user1).await.unwrap(), metrics_id1);
399    assert_eq!(db.get_user_metrics_id(user2).await.unwrap(), metrics_id2);
400    assert_eq!(metrics_id1.len(), 36);
401    assert_eq!(metrics_id2.len(), 36);
402    assert_ne!(metrics_id1, metrics_id2);
403});
404
405#[test]
406fn test_fuzzy_like_string() {
407    assert_eq!(Database::fuzzy_like_string("abcd"), "%a%b%c%d%");
408    assert_eq!(Database::fuzzy_like_string("x y"), "%x%y%");
409    assert_eq!(Database::fuzzy_like_string(" z  "), "%z%");
410}
411
412// #[gpui::test]
413// async fn test_fuzzy_search_users() {
414//     let test_db = PostgresTestDb::new(build_background_executor());
415//     let db = test_db.db();
416//     for (i, github_login) in [
417//         "California",
418//         "colorado",
419//         "oregon",
420//         "washington",
421//         "florida",
422//         "delaware",
423//         "rhode-island",
424//     ]
425//     .into_iter()
426//     .enumerate()
427//     {
428//         db.create_user(
429//             &format!("{github_login}@example.com"),
430//             false,
431//             NewUserParams {
432//                 github_login: github_login.into(),
433//                 github_user_id: i as i32,
434//                 invite_count: 0,
435//             },
436//         )
437//         .await
438//         .unwrap();
439//     }
440
441//     assert_eq!(
442//         fuzzy_search_user_names(db, "clr").await,
443//         &["colorado", "California"]
444//     );
445//     assert_eq!(
446//         fuzzy_search_user_names(db, "ro").await,
447//         &["rhode-island", "colorado", "oregon"],
448//     );
449
450//     async fn fuzzy_search_user_names(db: &Db<sqlx::Postgres>, query: &str) -> Vec<String> {
451//         db.fuzzy_search_users(query, 10)
452//             .await
453//             .unwrap()
454//             .into_iter()
455//             .map(|user| user.github_login)
456//             .collect::<Vec<_>>()
457//     }
458// }
459
460// #[gpui::test]
461// async fn test_invite_codes() {
462//     let test_db = PostgresTestDb::new(build_background_executor());
463//     let db = test_db.db();
464
465//     let NewUserResult { user_id: user1, .. } = db
466//         .create_user(
467//             "user1@example.com",
468//             false,
469//             NewUserParams {
470//                 github_login: "user1".into(),
471//                 github_user_id: 0,
472//                 invite_count: 0,
473//             },
474//         )
475//         .await
476//         .unwrap();
477
478//     // Initially, user 1 has no invite code
479//     assert_eq!(db.get_invite_code_for_user(user1).await.unwrap(), None);
480
481//     // Setting invite count to 0 when no code is assigned does not assign a new code
482//     db.set_invite_count_for_user(user1, 0).await.unwrap();
483//     assert!(db.get_invite_code_for_user(user1).await.unwrap().is_none());
484
485//     // User 1 creates an invite code that can be used twice.
486//     db.set_invite_count_for_user(user1, 2).await.unwrap();
487//     let (invite_code, invite_count) = db.get_invite_code_for_user(user1).await.unwrap().unwrap();
488//     assert_eq!(invite_count, 2);
489
490//     // User 2 redeems the invite code and becomes a contact of user 1.
491//     let user2_invite = db
492//         .create_invite_from_code(&invite_code, "user2@example.com", Some("user-2-device-id"))
493//         .await
494//         .unwrap();
495//     let NewUserResult {
496//         user_id: user2,
497//         inviting_user_id,
498//         signup_device_id,
499//         metrics_id,
500//     } = db
501//         .create_user_from_invite(
502//             &user2_invite,
503//             NewUserParams {
504//                 github_login: "user2".into(),
505//                 github_user_id: 2,
506//                 invite_count: 7,
507//             },
508//         )
509//         .await
510//         .unwrap()
511//         .unwrap();
512//     let (_, invite_count) = db.get_invite_code_for_user(user1).await.unwrap().unwrap();
513//     assert_eq!(invite_count, 1);
514//     assert_eq!(inviting_user_id, Some(user1));
515//     assert_eq!(signup_device_id.unwrap(), "user-2-device-id");
516//     assert_eq!(db.get_user_metrics_id(user2).await.unwrap(), metrics_id);
517//     assert_eq!(
518//         db.get_contacts(user1).await.unwrap(),
519//         [Contact::Accepted {
520//             user_id: user2,
521//             should_notify: true,
522//             busy: false,
523//         }]
524//     );
525//     assert_eq!(
526//         db.get_contacts(user2).await.unwrap(),
527//         [Contact::Accepted {
528//             user_id: user1,
529//             should_notify: false,
530//             busy: false,
531//         }]
532//     );
533//     assert_eq!(
534//         db.get_invite_code_for_user(user2).await.unwrap().unwrap().1,
535//         7
536//     );
537
538//     // User 3 redeems the invite code and becomes a contact of user 1.
539//     let user3_invite = db
540//         .create_invite_from_code(&invite_code, "user3@example.com", None)
541//         .await
542//         .unwrap();
543//     let NewUserResult {
544//         user_id: user3,
545//         inviting_user_id,
546//         signup_device_id,
547//         ..
548//     } = db
549//         .create_user_from_invite(
550//             &user3_invite,
551//             NewUserParams {
552//                 github_login: "user-3".into(),
553//                 github_user_id: 3,
554//                 invite_count: 3,
555//             },
556//         )
557//         .await
558//         .unwrap()
559//         .unwrap();
560//     let (_, invite_count) = db.get_invite_code_for_user(user1).await.unwrap().unwrap();
561//     assert_eq!(invite_count, 0);
562//     assert_eq!(inviting_user_id, Some(user1));
563//     assert!(signup_device_id.is_none());
564//     assert_eq!(
565//         db.get_contacts(user1).await.unwrap(),
566//         [
567//             Contact::Accepted {
568//                 user_id: user2,
569//                 should_notify: true,
570//                 busy: false,
571//             },
572//             Contact::Accepted {
573//                 user_id: user3,
574//                 should_notify: true,
575//                 busy: false,
576//             }
577//         ]
578//     );
579//     assert_eq!(
580//         db.get_contacts(user3).await.unwrap(),
581//         [Contact::Accepted {
582//             user_id: user1,
583//             should_notify: false,
584//             busy: false,
585//         }]
586//     );
587//     assert_eq!(
588//         db.get_invite_code_for_user(user3).await.unwrap().unwrap().1,
589//         3
590//     );
591
592//     // Trying to reedem the code for the third time results in an error.
593//     db.create_invite_from_code(&invite_code, "user4@example.com", Some("user-4-device-id"))
594//         .await
595//         .unwrap_err();
596
597//     // Invite count can be updated after the code has been created.
598//     db.set_invite_count_for_user(user1, 2).await.unwrap();
599//     let (latest_code, invite_count) = db.get_invite_code_for_user(user1).await.unwrap().unwrap();
600//     assert_eq!(latest_code, invite_code); // Invite code doesn't change when we increment above 0
601//     assert_eq!(invite_count, 2);
602
603//     // User 4 can now redeem the invite code and becomes a contact of user 1.
604//     let user4_invite = db
605//         .create_invite_from_code(&invite_code, "user4@example.com", Some("user-4-device-id"))
606//         .await
607//         .unwrap();
608//     let user4 = db
609//         .create_user_from_invite(
610//             &user4_invite,
611//             NewUserParams {
612//                 github_login: "user-4".into(),
613//                 github_user_id: 4,
614//                 invite_count: 5,
615//             },
616//         )
617//         .await
618//         .unwrap()
619//         .unwrap()
620//         .user_id;
621
622//     let (_, invite_count) = db.get_invite_code_for_user(user1).await.unwrap().unwrap();
623//     assert_eq!(invite_count, 1);
624//     assert_eq!(
625//         db.get_contacts(user1).await.unwrap(),
626//         [
627//             Contact::Accepted {
628//                 user_id: user2,
629//                 should_notify: true,
630//                 busy: false,
631//             },
632//             Contact::Accepted {
633//                 user_id: user3,
634//                 should_notify: true,
635//                 busy: false,
636//             },
637//             Contact::Accepted {
638//                 user_id: user4,
639//                 should_notify: true,
640//                 busy: false,
641//             }
642//         ]
643//     );
644//     assert_eq!(
645//         db.get_contacts(user4).await.unwrap(),
646//         [Contact::Accepted {
647//             user_id: user1,
648//             should_notify: false,
649//             busy: false,
650//         }]
651//     );
652//     assert_eq!(
653//         db.get_invite_code_for_user(user4).await.unwrap().unwrap().1,
654//         5
655//     );
656
657//     // An existing user cannot redeem invite codes.
658//     db.create_invite_from_code(&invite_code, "user2@example.com", Some("user-2-device-id"))
659//         .await
660//         .unwrap_err();
661//     let (_, invite_count) = db.get_invite_code_for_user(user1).await.unwrap().unwrap();
662//     assert_eq!(invite_count, 1);
663// }
664
665// #[gpui::test]
666// async fn test_signups() {
667//     let test_db = PostgresTestDb::new(build_background_executor());
668//     let db = test_db.db();
669
670//     // people sign up on the waitlist
671//     for i in 0..8 {
672//         db.create_signup(Signup {
673//             email_address: format!("person-{i}@example.com"),
674//             platform_mac: true,
675//             platform_linux: i % 2 == 0,
676//             platform_windows: i % 4 == 0,
677//             editor_features: vec!["speed".into()],
678//             programming_languages: vec!["rust".into(), "c".into()],
679//             device_id: Some(format!("device_id_{i}")),
680//         })
681//         .await
682//         .unwrap();
683//     }
684
685//     assert_eq!(
686//         db.get_waitlist_summary().await.unwrap(),
687//         WaitlistSummary {
688//             count: 8,
689//             mac_count: 8,
690//             linux_count: 4,
691//             windows_count: 2,
692//             unknown_count: 0,
693//         }
694//     );
695
696//     // retrieve the next batch of signup emails to send
697//     let signups_batch1 = db.get_unsent_invites(3).await.unwrap();
698//     let addresses = signups_batch1
699//         .iter()
700//         .map(|s| &s.email_address)
701//         .collect::<Vec<_>>();
702//     assert_eq!(
703//         addresses,
704//         &[
705//             "person-0@example.com",
706//             "person-1@example.com",
707//             "person-2@example.com"
708//         ]
709//     );
710//     assert_ne!(
711//         signups_batch1[0].email_confirmation_code,
712//         signups_batch1[1].email_confirmation_code
713//     );
714
715//     // the waitlist isn't updated until we record that the emails
716//     // were successfully sent.
717//     let signups_batch = db.get_unsent_invites(3).await.unwrap();
718//     assert_eq!(signups_batch, signups_batch1);
719
720//     // once the emails go out, we can retrieve the next batch
721//     // of signups.
722//     db.record_sent_invites(&signups_batch1).await.unwrap();
723//     let signups_batch2 = db.get_unsent_invites(3).await.unwrap();
724//     let addresses = signups_batch2
725//         .iter()
726//         .map(|s| &s.email_address)
727//         .collect::<Vec<_>>();
728//     assert_eq!(
729//         addresses,
730//         &[
731//             "person-3@example.com",
732//             "person-4@example.com",
733//             "person-5@example.com"
734//         ]
735//     );
736
737//     // the sent invites are excluded from the summary.
738//     assert_eq!(
739//         db.get_waitlist_summary().await.unwrap(),
740//         WaitlistSummary {
741//             count: 5,
742//             mac_count: 5,
743//             linux_count: 2,
744//             windows_count: 1,
745//             unknown_count: 0,
746//         }
747//     );
748
749//     // user completes the signup process by providing their
750//     // github account.
751//     let NewUserResult {
752//         user_id,
753//         inviting_user_id,
754//         signup_device_id,
755//         ..
756//     } = db
757//         .create_user_from_invite(
758//             &Invite {
759//                 email_address: signups_batch1[0].email_address.clone(),
760//                 email_confirmation_code: signups_batch1[0].email_confirmation_code.clone(),
761//             },
762//             NewUserParams {
763//                 github_login: "person-0".into(),
764//                 github_user_id: 0,
765//                 invite_count: 5,
766//             },
767//         )
768//         .await
769//         .unwrap()
770//         .unwrap();
771//     let user = db.get_user_by_id(user_id).await.unwrap().unwrap();
772//     assert!(inviting_user_id.is_none());
773//     assert_eq!(user.github_login, "person-0");
774//     assert_eq!(user.email_address.as_deref(), Some("person-0@example.com"));
775//     assert_eq!(user.invite_count, 5);
776//     assert_eq!(signup_device_id.unwrap(), "device_id_0");
777
778//     // cannot redeem the same signup again.
779//     assert!(db
780//         .create_user_from_invite(
781//             &Invite {
782//                 email_address: signups_batch1[0].email_address.clone(),
783//                 email_confirmation_code: signups_batch1[0].email_confirmation_code.clone(),
784//             },
785//             NewUserParams {
786//                 github_login: "some-other-github_account".into(),
787//                 github_user_id: 1,
788//                 invite_count: 5,
789//             },
790//         )
791//         .await
792//         .unwrap()
793//         .is_none());
794
795//     // cannot redeem a signup with the wrong confirmation code.
796//     db.create_user_from_invite(
797//         &Invite {
798//             email_address: signups_batch1[1].email_address.clone(),
799//             email_confirmation_code: "the-wrong-code".to_string(),
800//         },
801//         NewUserParams {
802//             github_login: "person-1".into(),
803//             github_user_id: 2,
804//             invite_count: 5,
805//         },
806//     )
807//     .await
808//     .unwrap_err();
809// }
810
811fn build_background_executor() -> Arc<Background> {
812    Deterministic::new(0).build_background()
813}