@@ -53,14 +53,22 @@ impl<'a> TryFrom<ReceiverConfig<'a>> for libdd_crashtracker::CrashtrackerReceive
5353 }
5454}
5555
56+ #[ repr( C ) ]
57+ pub struct EndpointConfig < ' a > {
58+ pub url : CharSlice < ' a > ,
59+ pub api_key : CharSlice < ' a > ,
60+ pub test_token : CharSlice < ' a > ,
61+ pub use_system_resolver : bool ,
62+ }
63+
5664#[ repr( C ) ]
5765pub struct Config < ' a > {
5866 pub additional_files : Slice < ' a , CharSlice < ' a > > ,
5967 pub create_alt_stack : bool ,
6068 pub demangle_names : bool ,
6169 /// The endpoint to send the crash report to (can be a file://).
6270 /// If None, the crashtracker will infer the agent host from env variables.
63- pub endpoint : CharSlice < ' a > ,
71+ pub endpoint : EndpointConfig < ' a > ,
6472 /// Optional filename for a unix domain socket if the receiver is used asynchonously
6573 pub optional_unix_socket_filename : CharSlice < ' a > ,
6674 pub resolve_frames : StacktraceCollection ,
@@ -93,8 +101,15 @@ impl<'a> TryFrom<Config<'a>> for libdd_crashtracker::CrashtrackerConfiguration {
93101 . demangle_names ( value. demangle_names )
94102 . resolve_frames ( value. resolve_frames )
95103 . signals ( value. signals . iter ( ) . copied ( ) . collect ( ) )
96- . use_alt_stack ( value. use_alt_stack ) ;
97- if let Some ( url) = value. endpoint . try_to_string_option ( ) ? {
104+ . use_alt_stack ( value. use_alt_stack )
105+ . endpoint_use_system_resolver ( value. endpoint . use_system_resolver ) ;
106+ if let Some ( api_key) = value. endpoint . api_key . try_to_string_option ( ) ? {
107+ builder = builder. endpoint_api_key ( & api_key) ;
108+ }
109+ if let Some ( test_token) = value. endpoint . test_token . try_to_string_option ( ) ? {
110+ builder = builder. endpoint_test_token ( & test_token) ;
111+ }
112+ if let Some ( url) = value. endpoint . url . try_to_string_option ( ) ? {
98113 builder = builder. endpoint_url ( & url) ;
99114 }
100115 if value. timeout_ms != 0 {
@@ -122,3 +137,281 @@ impl From<anyhow::Result<[i64; OpTypes::SIZE as usize]>> for CrashtrackerGetCoun
122137 }
123138 }
124139}
140+
141+ #[ cfg( test) ]
142+ mod tests {
143+ use super :: * ;
144+ use libdd_crashtracker:: CrashtrackerConfiguration ;
145+
146+ #[ test]
147+ fn test_config_try_from_defaults ( ) -> anyhow:: Result < ( ) > {
148+ let ffi_config = Config {
149+ additional_files : Slice :: empty ( ) ,
150+ create_alt_stack : false ,
151+ demangle_names : false ,
152+ endpoint : EndpointConfig {
153+ url : CharSlice :: empty ( ) ,
154+ api_key : CharSlice :: empty ( ) ,
155+ test_token : CharSlice :: empty ( ) ,
156+ use_system_resolver : false ,
157+ } ,
158+ optional_unix_socket_filename : CharSlice :: empty ( ) ,
159+ resolve_frames : StacktraceCollection :: Disabled ,
160+ signals : Slice :: empty ( ) ,
161+ timeout_ms : 0 ,
162+ use_alt_stack : false ,
163+ } ;
164+
165+ let config = CrashtrackerConfiguration :: try_from ( ffi_config) ?;
166+ let expected = CrashtrackerConfiguration :: builder ( ) . build ( ) ?;
167+ assert_eq ! ( config, expected) ;
168+ Ok ( ( ) )
169+ }
170+
171+ #[ test]
172+ fn test_config_try_from_endpoint_url ( ) -> anyhow:: Result < ( ) > {
173+ let ffi_config = Config {
174+ additional_files : Slice :: empty ( ) ,
175+ create_alt_stack : false ,
176+ demangle_names : false ,
177+ endpoint : EndpointConfig {
178+ url : CharSlice :: from ( "http://localhost:8126" ) ,
179+ api_key : CharSlice :: empty ( ) ,
180+ test_token : CharSlice :: empty ( ) ,
181+ use_system_resolver : false ,
182+ } ,
183+ optional_unix_socket_filename : CharSlice :: empty ( ) ,
184+ resolve_frames : StacktraceCollection :: Disabled ,
185+ signals : Slice :: empty ( ) ,
186+ timeout_ms : 0 ,
187+ use_alt_stack : false ,
188+ } ;
189+
190+ let config = CrashtrackerConfiguration :: try_from ( ffi_config) ?;
191+ let expected = CrashtrackerConfiguration :: builder ( )
192+ . endpoint_url ( "http://localhost:8126" )
193+ . build ( ) ?;
194+ assert_eq ! ( config, expected) ;
195+ Ok ( ( ) )
196+ }
197+
198+ #[ test]
199+ fn test_config_try_from_endpoint_api_key ( ) -> anyhow:: Result < ( ) > {
200+ let ffi_config = Config {
201+ additional_files : Slice :: empty ( ) ,
202+ create_alt_stack : false ,
203+ demangle_names : false ,
204+ endpoint : EndpointConfig {
205+ url : CharSlice :: from ( "http://localhost:8126" ) ,
206+ api_key : CharSlice :: from ( "my-api-key" ) ,
207+ test_token : CharSlice :: empty ( ) ,
208+ use_system_resolver : false ,
209+ } ,
210+ optional_unix_socket_filename : CharSlice :: empty ( ) ,
211+ resolve_frames : StacktraceCollection :: Disabled ,
212+ signals : Slice :: empty ( ) ,
213+ timeout_ms : 0 ,
214+ use_alt_stack : false ,
215+ } ;
216+
217+ let config = CrashtrackerConfiguration :: try_from ( ffi_config) ?;
218+ let expected = CrashtrackerConfiguration :: builder ( )
219+ . endpoint_url ( "http://localhost:8126" )
220+ . endpoint_api_key ( "my-api-key" )
221+ . build ( ) ?;
222+ assert_eq ! ( config, expected) ;
223+ Ok ( ( ) )
224+ }
225+
226+ #[ test]
227+ fn test_config_try_from_endpoint_test_token ( ) -> anyhow:: Result < ( ) > {
228+ let ffi_config = Config {
229+ additional_files : Slice :: empty ( ) ,
230+ create_alt_stack : false ,
231+ demangle_names : false ,
232+ endpoint : EndpointConfig {
233+ url : CharSlice :: from ( "http://localhost:8126" ) ,
234+ api_key : CharSlice :: empty ( ) ,
235+ test_token : CharSlice :: from ( "test-session-token" ) ,
236+ use_system_resolver : false ,
237+ } ,
238+ optional_unix_socket_filename : CharSlice :: empty ( ) ,
239+ resolve_frames : StacktraceCollection :: Disabled ,
240+ signals : Slice :: empty ( ) ,
241+ timeout_ms : 0 ,
242+ use_alt_stack : false ,
243+ } ;
244+
245+ let config = CrashtrackerConfiguration :: try_from ( ffi_config) ?;
246+ let expected = CrashtrackerConfiguration :: builder ( )
247+ . endpoint_url ( "http://localhost:8126" )
248+ . endpoint_test_token ( "test-session-token" )
249+ . build ( ) ?;
250+ assert_eq ! ( config, expected) ;
251+ Ok ( ( ) )
252+ }
253+
254+ #[ test]
255+ fn test_config_try_from_endpoint_use_system_resolver ( ) -> anyhow:: Result < ( ) > {
256+ let ffi_config = Config {
257+ additional_files : Slice :: empty ( ) ,
258+ create_alt_stack : false ,
259+ demangle_names : false ,
260+ endpoint : EndpointConfig {
261+ url : CharSlice :: from ( "http://localhost:8126" ) ,
262+ api_key : CharSlice :: empty ( ) ,
263+ test_token : CharSlice :: empty ( ) ,
264+ use_system_resolver : true ,
265+ } ,
266+ optional_unix_socket_filename : CharSlice :: empty ( ) ,
267+ resolve_frames : StacktraceCollection :: Disabled ,
268+ signals : Slice :: empty ( ) ,
269+ timeout_ms : 0 ,
270+ use_alt_stack : false ,
271+ } ;
272+
273+ let config = CrashtrackerConfiguration :: try_from ( ffi_config) ?;
274+ let expected = CrashtrackerConfiguration :: builder ( )
275+ . endpoint_url ( "http://localhost:8126" )
276+ . endpoint_use_system_resolver ( true )
277+ . build ( ) ?;
278+ assert_eq ! ( config, expected) ;
279+ Ok ( ( ) )
280+ }
281+
282+ #[ test]
283+ fn test_config_try_from_timeout_zero_uses_default ( ) -> anyhow:: Result < ( ) > {
284+ let ffi_config = Config {
285+ additional_files : Slice :: empty ( ) ,
286+ create_alt_stack : false ,
287+ demangle_names : false ,
288+ endpoint : EndpointConfig {
289+ url : CharSlice :: empty ( ) ,
290+ api_key : CharSlice :: empty ( ) ,
291+ test_token : CharSlice :: empty ( ) ,
292+ use_system_resolver : false ,
293+ } ,
294+ optional_unix_socket_filename : CharSlice :: empty ( ) ,
295+ resolve_frames : StacktraceCollection :: Disabled ,
296+ signals : Slice :: empty ( ) ,
297+ timeout_ms : 0 ,
298+ use_alt_stack : false ,
299+ } ;
300+
301+ let config = CrashtrackerConfiguration :: try_from ( ffi_config) ?;
302+ let expected = CrashtrackerConfiguration :: builder ( ) . build ( ) ?;
303+ assert_eq ! ( config. timeout( ) , expected. timeout( ) ) ;
304+ Ok ( ( ) )
305+ }
306+
307+ #[ test]
308+ fn test_config_try_from_custom_timeout ( ) -> anyhow:: Result < ( ) > {
309+ use std:: time:: Duration ;
310+
311+ let ffi_config = Config {
312+ additional_files : Slice :: empty ( ) ,
313+ create_alt_stack : false ,
314+ demangle_names : false ,
315+ endpoint : EndpointConfig {
316+ url : CharSlice :: empty ( ) ,
317+ api_key : CharSlice :: empty ( ) ,
318+ test_token : CharSlice :: empty ( ) ,
319+ use_system_resolver : false ,
320+ } ,
321+ optional_unix_socket_filename : CharSlice :: empty ( ) ,
322+ resolve_frames : StacktraceCollection :: Disabled ,
323+ signals : Slice :: empty ( ) ,
324+ timeout_ms : 5000 ,
325+ use_alt_stack : false ,
326+ } ;
327+
328+ let config = CrashtrackerConfiguration :: try_from ( ffi_config) ?;
329+ let expected = CrashtrackerConfiguration :: builder ( )
330+ . timeout ( Duration :: from_millis ( 5000 ) )
331+ . build ( ) ?;
332+ assert_eq ! ( config, expected) ;
333+ Ok ( ( ) )
334+ }
335+
336+ #[ test]
337+ fn test_config_try_from_unix_socket ( ) -> anyhow:: Result < ( ) > {
338+ let ffi_config = Config {
339+ additional_files : Slice :: empty ( ) ,
340+ create_alt_stack : false ,
341+ demangle_names : false ,
342+ endpoint : EndpointConfig {
343+ url : CharSlice :: empty ( ) ,
344+ api_key : CharSlice :: empty ( ) ,
345+ test_token : CharSlice :: empty ( ) ,
346+ use_system_resolver : false ,
347+ } ,
348+ optional_unix_socket_filename : CharSlice :: from ( "/run/crashtracker.sock" ) ,
349+ resolve_frames : StacktraceCollection :: Disabled ,
350+ signals : Slice :: empty ( ) ,
351+ timeout_ms : 0 ,
352+ use_alt_stack : false ,
353+ } ;
354+
355+ let config = CrashtrackerConfiguration :: try_from ( ffi_config) ?;
356+ let expected = CrashtrackerConfiguration :: builder ( )
357+ . unix_socket_path ( "/run/crashtracker.sock" . to_string ( ) )
358+ . build ( ) ?;
359+ assert_eq ! ( config, expected) ;
360+ Ok ( ( ) )
361+ }
362+
363+ #[ test]
364+ fn test_config_try_from_additional_files ( ) -> anyhow:: Result < ( ) > {
365+ let file1 = CharSlice :: from ( "/tmp/extra1.txt" ) ;
366+ let file2 = CharSlice :: from ( "/tmp/extra2.txt" ) ;
367+ let files = [ file1, file2] ;
368+ let ffi_config = Config {
369+ additional_files : Slice :: from ( files. as_slice ( ) ) ,
370+ create_alt_stack : false ,
371+ demangle_names : false ,
372+ endpoint : EndpointConfig {
373+ url : CharSlice :: empty ( ) ,
374+ api_key : CharSlice :: empty ( ) ,
375+ test_token : CharSlice :: empty ( ) ,
376+ use_system_resolver : false ,
377+ } ,
378+ optional_unix_socket_filename : CharSlice :: empty ( ) ,
379+ resolve_frames : StacktraceCollection :: Disabled ,
380+ signals : Slice :: empty ( ) ,
381+ timeout_ms : 0 ,
382+ use_alt_stack : false ,
383+ } ;
384+
385+ let config = CrashtrackerConfiguration :: try_from ( ffi_config) ?;
386+ let expected = CrashtrackerConfiguration :: builder ( )
387+ . additional_files ( vec ! [
388+ "/tmp/extra1.txt" . to_string( ) ,
389+ "/tmp/extra2.txt" . to_string( ) ,
390+ ] )
391+ . build ( ) ?;
392+ assert_eq ! ( config, expected) ;
393+ Ok ( ( ) )
394+ }
395+
396+ #[ test]
397+ fn test_config_try_from_create_alt_stack_without_use_fails ( ) {
398+ let ffi_config = Config {
399+ additional_files : Slice :: empty ( ) ,
400+ create_alt_stack : true ,
401+ demangle_names : false ,
402+ endpoint : EndpointConfig {
403+ url : CharSlice :: empty ( ) ,
404+ api_key : CharSlice :: empty ( ) ,
405+ test_token : CharSlice :: empty ( ) ,
406+ use_system_resolver : false ,
407+ } ,
408+ optional_unix_socket_filename : CharSlice :: empty ( ) ,
409+ resolve_frames : StacktraceCollection :: Disabled ,
410+ signals : Slice :: empty ( ) ,
411+ timeout_ms : 0 ,
412+ use_alt_stack : false ,
413+ } ;
414+
415+ assert ! ( CrashtrackerConfiguration :: try_from( ffi_config) . is_err( ) ) ;
416+ }
417+ }
0 commit comments