@@ -257,6 +257,51 @@ fn test_cyrillic() {
257257 assert_eq ! ( trace. frames[ 1 ] . line, 7 ) ;
258258}
259259
260+ #[ test]
261+ fn test_class_name ( ) {
262+ #[ cfg( target_os = "macos" ) ]
263+ {
264+ // We need root permissions here to run this on OSX
265+ if unsafe { libc:: geteuid ( ) } != 0 {
266+ return ;
267+ }
268+ }
269+
270+ let config = Config {
271+ include_class_name : true ,
272+ ..Default :: default ( )
273+ } ;
274+
275+ let mut runner = TestRunner :: new ( config, "./tests/scripts/class_name.py" ) ;
276+ let traces = runner. spy . get_stack_traces ( ) . unwrap ( ) ;
277+ assert_eq ! ( traces. len( ) , 1 ) ;
278+ let trace = & traces[ 0 ] ;
279+
280+ let frames: Vec < & str > = trace
281+ . frames
282+ . iter ( )
283+ . rev ( )
284+ . map ( |frame| frame. name . as_ref ( ) )
285+ . collect ( ) ;
286+
287+ assert_eq ! (
288+ frames,
289+ [
290+ "<module>" ,
291+ "normal_function" ,
292+ "normal_function_with_arg" ,
293+ "normal_function_with_non_arg_local_called_self" ,
294+ "normal_function_with_non_arg_local_called_cls" ,
295+ "object.normal_function_with_a_confusing_self_arg" , // first arg confused with self - room for improvement
296+ "object.normal_function_with_a_confusing_cls_arg" , // first arg confused with cls - room for improvement
297+ "SomeClass.class_method" , // correctly recognised class
298+ "class_method_confusing_first_arg" , // class arg name doesn't follow the convention - not recognised
299+ "SomeClass.normal_method" , // correctly recognised class instance
300+ "normal_method_confusing_first_arg" , // self arg name doesn't follow the convention - not recognised
301+ ]
302+ ) ;
303+ }
304+
260305#[ test]
261306fn test_local_vars ( ) {
262307 #[ cfg( target_os = "macos" ) ]
@@ -335,6 +380,57 @@ fn test_local_vars() {
335380 }
336381}
337382
383+ #[ test]
384+ fn test_local_vars_and_class_name ( ) {
385+ #[ cfg( target_os = "macos" ) ]
386+ {
387+ // We need root permissions here to run this on OSX
388+ if unsafe { libc:: geteuid ( ) } != 0 {
389+ return ;
390+ }
391+ }
392+
393+ let config = Config {
394+ dump_locals : 1 ,
395+ include_class_name : true ,
396+ ..Default :: default ( )
397+ } ;
398+ let mut runner = TestRunner :: new ( config, "./tests/scripts/local_vars_and_class_name.py" ) ;
399+ let traces = runner. spy . get_stack_traces ( ) . unwrap ( ) ;
400+ assert_eq ! ( traces. len( ) , 1 ) ;
401+ let trace = & traces[ 0 ] ;
402+ assert_eq ! ( trace. frames. len( ) , 2 ) ;
403+
404+ let fn_frame = & trace. frames [ 0 ] ;
405+ assert_eq ! ( fn_frame. name, "ClassName.local_variable_lookup" ) ;
406+
407+ let locals = fn_frame. locals . as_ref ( ) . unwrap ( ) ;
408+
409+ assert_eq ! ( locals[ 0 ] . name, "self" ) ;
410+ assert_eq ! ( locals[ 0 ] . arg, true ) ;
411+ assert ! ( locals[ 0 ]
412+ . repr
413+ . as_ref( )
414+ . expect( "class repr should be given" )
415+ . starts_with( "<ClassName at 0x" ) ) ;
416+
417+ let remaining_locals: Vec < ( & str , bool , Option < & str > ) > = locals
418+ . iter ( )
419+ . skip ( 1 )
420+ . map ( |local| ( local. name . as_ref ( ) , local. arg , local. repr . as_deref ( ) ) )
421+ . collect ( ) ;
422+
423+ assert_eq ! (
424+ remaining_locals,
425+ [
426+ ( "arg1" , true , Some ( "\" foo\" " , ) , ) ,
427+ ( "local1" , false , Some ( "\" a\" " , ) , ) ,
428+ ( "local2" , false , Some ( "2.71828" , ) , ) ,
429+ ( "local3" , false , Some ( "{}" , ) , ) ,
430+ ]
431+ ) ;
432+ }
433+
338434#[ cfg( not( target_os = "freebsd" ) ) ]
339435#[ test]
340436fn test_subprocesses ( ) {
0 commit comments