1use diesel::result::DatabaseErrorKind;
2use rand::{
4 Rng,
5 distributions::{Distribution, Standard},
6 prelude::IteratorRandom,
7};
8use xmtp_proto::types::Cursor;
9
10use crate::{
11 DuplicateItem, NotFound, StorageError, refresh_state::EntityKind,
12 sql_key_store::SqlKeyStoreError,
13};
14
15impl Distribution<StorageError> for Standard {
18 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> StorageError {
19 match rng.gen_range(0..=13) {
20 0 => StorageError::DieselConnect(rand_diesel_conn_err(rng)),
21 1 => StorageError::DieselResult(rand_diesel_result(rng)),
22 2 => StorageError::NotFound(rand::random()),
23 3 => StorageError::Duplicate(DuplicateItem::WelcomeId(Some(Cursor::default()))),
24 4 => rand::random(),
25 5 => StorageError::IntentionalRollback,
26 6 => StorageError::DbSerialize,
27 7 => StorageError::DbDeserialize,
28 8 => StorageError::Builder(derive_builder::UninitializedFieldError::new("test field")),
29 10 => rand::random(), 11 => StorageError::Prost(prost::DecodeError::new("test random decode error")),
31 12 => StorageError::Connection(rand::random()),
32 13 => StorageError::Conversion(xmtp_proto::ConversionError::Unspecified(
33 "random test error",
34 )),
35 _ => unreachable!(),
36 }
37 }
38}
39
40impl Distribution<SqlKeyStoreError> for Standard {
41 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> SqlKeyStoreError {
42 use SqlKeyStoreError::*;
43 match rng.gen_range(0..=5) {
44 0 => UnsupportedValueTypeBytes,
45 1 => UnsupportedMethod,
46 2 => SerializationError,
47 3 => NotFound,
48 4 => Storage(rand_diesel_result(rng)),
49 5 => Connection(rand::random()),
50 _ => unreachable!(),
51 }
52 }
53}
54
55impl Distribution<NotFound> for Standard {
56 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> NotFound {
57 match rng.gen_range(0..=13) {
58 0 => NotFound::GroupByWelcome(Cursor::default()),
59 1 => NotFound::GroupById(Vec::new()),
60 2 => NotFound::InstallationTimeForGroup(Vec::new()),
61 3 => NotFound::InboxIdForAddress("random test inbox".into()),
62 4 => NotFound::MessageById(Vec::new()),
63 5 => NotFound::DmByInbox("random dm by inbox".into()),
64 6 => NotFound::IntentForToPublish(i32::MAX),
65 7 => NotFound::IntentForPublish(i32::MAX),
66 8 => NotFound::IntentForCommitted(i32::MIN),
67 9 => NotFound::IntentById(i32::MIN),
68 10 => NotFound::RefreshStateByIdKindAndOriginator(
69 Vec::new(),
70 EntityKind::ApplicationMessage,
71 0,
72 ),
73 11 => NotFound::CipherSalt("random salt for testing".into()),
74 12 => NotFound::SyncGroup(xmtp_common::rand_array::<32>().into()),
75 13 => NotFound::MlsGroup,
76 _ => unreachable!(),
77 }
78 }
79}
80
81impl Distribution<crate::ConnectionError> for Standard {
82 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> crate::ConnectionError {
83 match rng.gen_range(0..=1) {
84 0 => crate::ConnectionError::Database(rand_diesel_result(rng)),
85 1 => crate::ConnectionError::Platform(rand::random()),
86 _ => unreachable!(),
87 }
88 }
89}
90
91fn rand_diesel_conn_err<R: Rng + ?Sized>(rng: &mut R) -> diesel::ConnectionError {
92 use diesel::ConnectionError::*;
93 vec![
94 diesel::ConnectionError::InvalidCString(
95 std::ffi::CString::new(b"f\0oo".to_vec()).unwrap_err(),
96 ),
97 BadConnection("rand bad connection err".into()),
98 InvalidConnectionUrl("bad conn url".into()),
99 CouldntSetupConfiguration(rand_diesel_result(rng)),
100 ]
101 .into_iter()
102 .choose(rng)
103 .unwrap()
104}
105
106fn rand_diesel_result<R: Rng + ?Sized>(rng: &mut R) -> diesel::result::Error {
107 use diesel::result::Error::*;
108 vec![
109 InvalidCString(std::ffi::CString::new(b"f\0oo".to_vec()).unwrap_err()),
110 DatabaseError(
111 rand_db_error(rng),
112 Box::new("Random Db Test Error".to_string()),
113 ),
114 diesel::result::Error::NotFound,
115 QueryBuilderError(Box::new(std::io::Error::other("Rand query builder error"))),
116 DeserializationError(Box::new(std::io::Error::other(
117 "rand deserialization error",
118 ))),
119 SerializationError(Box::new(std::io::Error::other("Rand serialization error"))),
120 RollbackTransaction,
121 AlreadyInTransaction,
122 NotInTransaction,
123 ]
124 .into_iter()
125 .choose(rng)
126 .unwrap()
127}
128
129fn rand_db_error<R: Rng + ?Sized>(rng: &mut R) -> DatabaseErrorKind {
130 use DatabaseErrorKind::*;
131 vec![
132 UniqueViolation,
133 ForeignKeyViolation,
134 UnableToSendCommand,
135 SerializationFailure,
136 ReadOnlyTransaction,
137 RestrictViolation,
138 NotNullViolation,
139 CheckViolation,
140 ExclusionViolation,
141 ClosedConnection,
142 Unknown,
143 ]
144 .into_iter()
145 .choose(rng)
146 .unwrap()
147}
148
149#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
150mod native {
151 use crate::PlatformStorageError;
152
153 use super::*;
154 impl Distribution<PlatformStorageError> for Standard {
155 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> PlatformStorageError {
156 match rng.gen_range(0..=9) {
157 0 => PlatformStorageError::DbConnection(rand_r2d2_err(rng)),
158 1 => PlatformStorageError::PoolNeedsConnection,
159 2 => PlatformStorageError::SqlCipherNotLoaded,
160 3 => PlatformStorageError::SqlCipherKeyIncorrect,
161 4 => PlatformStorageError::DieselResult(rand_diesel_result(rng)),
162 5 => PlatformStorageError::NotFound(rand::random()),
163 6 => PlatformStorageError::Io(std::io::Error::other("test io error")),
164 7 => PlatformStorageError::FromHex(hex::FromHexError::OddLength),
165 8 => PlatformStorageError::DieselConnect(rand_diesel_conn_err(rng)),
166 9 => {
167 PlatformStorageError::Boxed(Box::new(std::io::Error::other("test boxed error")))
168 }
169 _ => unreachable!(),
170 }
171 }
172 }
173
174 fn rand_r2d2_err<R: Rng + ?Sized>(rng: &mut R) -> diesel::r2d2::Error {
175 match rng.gen_range(0..=1) {
176 0 => diesel::r2d2::Error::ConnectionError(rand_diesel_conn_err(rng)),
177 1 => diesel::r2d2::Error::QueryError(rand_diesel_result(rng)),
178 _ => unreachable!(),
179 }
180 }
181}
182
183#[cfg(all(target_family = "wasm", target_os = "unknown"))]
184mod wasm {
185 use crate::PlatformStorageError;
186
187 use super::*;
188 impl Distribution<crate::PlatformStorageError> for Standard {
189 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> crate::PlatformStorageError {
190 match rng.gen_range(0..=2) {
191 0 => PlatformStorageError::SAH(sqlite_wasm_rs::sahpool_vfs::OpfsSAHError::Generic(
192 "rand test opfs err".to_string(),
193 )),
194 1 => PlatformStorageError::Connection(rand_diesel_conn_err(rng)),
195 2 => PlatformStorageError::DieselResult(rand_diesel_result(rng)),
196 _ => unreachable!(),
197 }
198 }
199 }
200}