open_lark/service/im/
mod.rs1use crate::{
44 core::config::Config,
45 service::im::{v1::V1, v2::V2},
46};
47
48pub mod v1;
50pub mod v2;
52
53pub struct ImService {
58 pub v1: V1,
60 pub v2: V2,
62}
63
64impl ImService {
65 pub fn new(config: Config) -> Self {
70 Self {
71 v1: V1::new(config.clone()),
72 v2: V2::new(config),
73 }
74 }
75
76 pub fn new_from_shared(shared: std::sync::Arc<Config>) -> Self {
78 Self {
79 v1: V1::new(shared.as_ref().clone()),
80 v2: V2::new(shared.as_ref().clone()),
81 }
82 }
83}
84
85#[cfg(test)]
86#[allow(unused_variables, unused_unsafe)]
87mod tests {
88 use super::*;
89 use crate::core::config::Config;
90
91 fn create_test_config() -> Config {
92 Config::default()
93 }
94
95 #[test]
96 fn test_im_service_creation() {
97 let config = create_test_config();
98 let im_service = ImService::new(config);
99
100 }
102
103 #[test]
104 fn test_im_service_with_custom_config() {
105 let config = Config::builder()
106 .app_id("im_app")
107 .app_secret("im_secret")
108 .req_timeout(std::time::Duration::from_millis(12000))
109 .base_url("https://im.api.com")
110 .build();
111
112 let im_service = ImService::new(config);
113
114 }
116
117 #[test]
118 fn test_im_service_api_versions_independence() {
119 let config = create_test_config();
120 let im_service = ImService::new(config);
121
122 let v1_ptr = std::ptr::addr_of!(im_service.v1) as *const _;
124 let v2_ptr = std::ptr::addr_of!(im_service.v2) as *const _;
125
126 assert_ne!(v1_ptr, v2_ptr, "API versions should be independent");
127 }
128
129 #[test]
130 fn test_im_service_with_various_configurations() {
131 let test_configs = vec![
132 Config::builder()
133 .app_id("im_basic")
134 .app_secret("basic_secret")
135 .build(),
136 Config::builder()
137 .app_id("im_timeout")
138 .app_secret("timeout_secret")
139 .req_timeout(std::time::Duration::from_millis(18000))
140 .build(),
141 Config::builder()
142 .app_id("im_custom")
143 .app_secret("custom_secret")
144 .base_url("https://custom.im.com")
145 .build(),
146 Config::builder()
147 .app_id("im_full")
148 .app_secret("full_secret")
149 .req_timeout(std::time::Duration::from_millis(22000))
150 .base_url("https://full.im.com")
151 .enable_token_cache(false)
152 .build(),
153 ];
154
155 for config in test_configs {
156 let im_service = ImService::new(config);
157
158 }
160 }
161
162 #[test]
163 fn test_im_service_multiple_instances() {
164 let config1 = create_test_config();
165 let config2 = Config::builder()
166 .app_id("im2")
167 .app_secret("secret2")
168 .build();
169
170 let im_service1 = ImService::new(config1);
171 let im_service2 = ImService::new(config2);
172
173 let service1_ptr = std::ptr::addr_of!(im_service1) as *const _;
175 let service2_ptr = std::ptr::addr_of!(im_service2) as *const _;
176
177 assert_ne!(
178 service1_ptr, service2_ptr,
179 "Services should be independent instances"
180 );
181
182 }
184
185 #[test]
186 fn test_im_service_config_cloning_behavior() {
187 let original_config = create_test_config();
188
189 let im_service1 = ImService::new(original_config.clone());
191 let im_service2 = ImService::new(original_config);
192
193 let service1_ptr = std::ptr::addr_of!(im_service1) as *const u8;
197 let service2_ptr = std::ptr::addr_of!(im_service2) as *const u8;
198 assert_ne!(service1_ptr, service2_ptr);
199 }
200
201 #[test]
202 fn test_im_service_v1_v2_api_access() {
203 let config = create_test_config();
204 let im_service = ImService::new(config);
205
206 let v1_ptr = std::ptr::addr_of!(im_service.v1) as *const u8;
208 let v2_ptr = std::ptr::addr_of!(im_service.v2) as *const u8;
209
210 assert!(
211 !v1_ptr.is_null(),
212 "V1 service should be properly instantiated"
213 );
214 assert!(
215 !v2_ptr.is_null(),
216 "V2 service should be properly instantiated"
217 );
218 assert_ne!(
219 v1_ptr, v2_ptr,
220 "V1 and V2 services should be independent instances"
221 );
222 }
223
224 #[test]
225 fn test_im_service_v1_api_completeness() {
226 let config = create_test_config();
227 let im_service = ImService::new(config);
228
229 let v1_ptr = std::ptr::addr_of!(im_service.v1) as *const u8;
231 assert!(!v1_ptr.is_null(), "V1 IM API should be instantiated");
232 }
233
234 #[test]
235 fn test_im_service_v2_api_completeness() {
236 let config = create_test_config();
237 let im_service = ImService::new(config);
238
239 let v2_ptr = std::ptr::addr_of!(im_service.v2) as *const u8;
241 assert!(!v2_ptr.is_null(), "V2 IM API should be instantiated");
242 }
243
244 #[test]
245 fn test_im_service_concurrent_creation() {
246 let configs = vec![
247 Config::builder()
248 .app_id("im_concurrent_1")
249 .app_secret("secret_1")
250 .build(),
251 Config::builder()
252 .app_id("im_concurrent_2")
253 .app_secret("secret_2")
254 .build(),
255 Config::builder()
256 .app_id("im_concurrent_3")
257 .app_secret("secret_3")
258 .build(),
259 ];
260
261 let mut services = Vec::new();
262 for config in configs {
263 let service = ImService::new(config);
264 services.push(service);
265 }
266
267 assert_eq!(services.len(), 3);
269
270 for (i, service1) in services.iter().enumerate() {
272 for service2 in services.iter().skip(i + 1) {
273 let ptr1 = std::ptr::addr_of!(*service1) as *const u8;
274 let ptr2 = std::ptr::addr_of!(*service2) as *const u8;
275 assert_ne!(ptr1, ptr2, "Services should be independent instances");
276 }
277 }
278 }
279
280 #[test]
281 fn test_im_service_extreme_configurations() {
282 let extreme_configs = vec![
283 Config::builder()
285 .app_id("im_fast")
286 .app_secret("fast_secret")
287 .req_timeout(std::time::Duration::from_millis(100))
288 .build(),
289 Config::builder()
291 .app_id("im_slow")
292 .app_secret("slow_secret")
293 .req_timeout(std::time::Duration::from_secs(300))
294 .build(),
295 Config::builder()
297 .app_id("im_no_cache")
298 .app_secret("no_cache_secret")
299 .enable_token_cache(false)
300 .build(),
301 Config::builder()
303 .app_id("im_custom_base")
304 .app_secret("custom_base_secret")
305 .base_url("https://custom.im.api.endpoint")
306 .build(),
307 ];
308
309 for config in extreme_configs {
310 let im_service = ImService::new(config);
311
312 let service_ptr = std::ptr::addr_of!(im_service) as *const u8;
314 assert!(
315 !service_ptr.is_null(),
316 "Service should be created with extreme config"
317 );
318 }
319 }
320
321 #[test]
322 fn test_im_service_api_version_structure() {
323 let config = create_test_config();
324 let im_service = ImService::new(config);
325
326 let v1_offset = unsafe {
328 std::ptr::addr_of!(im_service.v1) as usize - std::ptr::addr_of!(im_service) as usize
329 };
330 let v2_offset = unsafe {
331 std::ptr::addr_of!(im_service.v2) as usize - std::ptr::addr_of!(im_service) as usize
332 };
333
334 assert_ne!(
336 v1_offset, v2_offset,
337 "V1 and V2 should occupy different memory positions"
338 );
339
340 assert!(v1_offset < 4096, "V1 offset should be reasonable");
342 assert!(v2_offset < 4096, "V2 offset should be reasonable");
343 }
344
345 #[test]
346 fn test_im_service_memory_consistency() {
347 let config = create_test_config();
348 let im_service = ImService::new(config);
349
350 let service_ptr1 = std::ptr::addr_of!(im_service) as *const u8;
352 let service_ptr2 = std::ptr::addr_of!(im_service) as *const u8;
353
354 assert_eq!(
355 service_ptr1, service_ptr2,
356 "Service memory address should be consistent"
357 );
358
359 let v1_ptr1 = std::ptr::addr_of!(im_service.v1) as *const u8;
361 let v1_ptr2 = std::ptr::addr_of!(im_service.v1) as *const u8;
362 let v2_ptr1 = std::ptr::addr_of!(im_service.v2) as *const u8;
363 let v2_ptr2 = std::ptr::addr_of!(im_service.v2) as *const u8;
364
365 assert_eq!(
366 v1_ptr1, v1_ptr2,
367 "V1 API memory address should be consistent"
368 );
369 assert_eq!(
370 v2_ptr1, v2_ptr2,
371 "V2 API memory address should be consistent"
372 );
373 }
374
375 #[test]
376 fn test_im_service_config_variations() {
377 let variations = vec![
378 (
379 "minimal",
380 Config::builder()
381 .app_id("minimal")
382 .app_secret("secret")
383 .build(),
384 ),
385 (
386 "with_timeout",
387 Config::builder()
388 .app_id("timeout")
389 .app_secret("secret")
390 .req_timeout(std::time::Duration::from_millis(30000))
391 .build(),
392 ),
393 (
394 "with_base_url",
395 Config::builder()
396 .app_id("base_url")
397 .app_secret("secret")
398 .base_url("https://test.api.com")
399 .build(),
400 ),
401 (
402 "full_featured",
403 Config::builder()
404 .app_id("full")
405 .app_secret("secret")
406 .req_timeout(std::time::Duration::from_millis(45000))
407 .base_url("https://full.test.api.com")
408 .enable_token_cache(true)
409 .build(),
410 ),
411 ];
412
413 let mut services = Vec::new();
414 for (name, config) in variations {
415 let service = ImService::new(config);
416 services.push((name, service));
417 }
418
419 assert_eq!(services.len(), 4);
421
422 for (i, (_, service1)) in services.iter().enumerate() {
424 for (_, service2) in services.iter().skip(i + 1) {
425 let ptr1 = std::ptr::addr_of!(*service1) as *const u8;
426 let ptr2 = std::ptr::addr_of!(*service2) as *const u8;
427 assert_ne!(
428 ptr1, ptr2,
429 "Services with different configs should be independent"
430 );
431 }
432 }
433 }
434}