[svn:parrot] r47381 - in branches/gsoc_instrument: src/dynpmc t/dynpmc

khairul at svn.parrot.org khairul at svn.parrot.org
Sat Jun 5 12:10:04 UTC 2010


Author: khairul
Date: Sat Jun  5 12:10:02 2010
New Revision: 47381
URL: https://trac.parrot.org/parrot/changeset/47381

Log:
Added tests for hook insertion and removal.

Modified:
   branches/gsoc_instrument/src/dynpmc/instrument.pmc
   branches/gsoc_instrument/t/dynpmc/instrument.t

Modified: branches/gsoc_instrument/src/dynpmc/instrument.pmc
==============================================================================
--- branches/gsoc_instrument/src/dynpmc/instrument.pmc	Sat Jun  5 11:34:24 2010	(r47380)
+++ branches/gsoc_instrument/src/dynpmc/instrument.pmc	Sat Jun  5 12:10:02 2010	(r47381)
@@ -322,18 +322,28 @@
     METHOD insert_op_hook (PMC *id, INTVAL op_num, PMC *hook) {
         Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
         Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
-        probe_list_t **list = core->op_hooks;
+        probe_list_t        **list = core->op_hooks;
+        size_t               index = op_num;
         
-        if(list[op_num] == NULL) {
-            list[op_num] = probe_list_create_list(INTERP);
+        if(index >= attr->supervised->op_count) {
+            /* Invalid op num */
+            Parrot_ex_throw_from_c_args(
+                INTERP, NULL, 1,
+                "Invalid op number %d.",
+                index
+            );
         }
         
-        probe_list_push(INTERP, list[op_num], hook);
+        if(list[index] == NULL) {
+            list[index] = probe_list_create_list(INTERP);
+        }
+        
+        probe_list_push(INTERP, list[index], hook);
     }
 
 /*
 
-=item C<void *remove_op_hooks(PMC *id, INTVAL op_num)>
+=item C<void *remove_op_hooks(PMC *id, INTVAL op_num, PMC *callback)>
 
 Removes a hook for the given op number.
 
@@ -344,16 +354,59 @@
     METHOD remove_op_hook (PMC *id, INTVAL op_num, PMC *callback) {
         Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
         Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
-        probe_list_t **list = core->op_hooks;
-        probe_node_t  *node = NULL;
+        probe_list_t        **list = core->op_hooks;
+        probe_node_t         *node = NULL;
+        size_t               index = op_num;
+        
+        if(index >= attr->supervised->op_count) {
+            /* Invalid op num */
+            Parrot_ex_throw_from_c_args(
+                INTERP, NULL, 1,
+                "Invalid op number %d.",
+                index
+            );
+        }
         
-        if(list[op_num] != NULL) {
-            node = probe_list_find(INTERP, list[op_num], callback);
+        if(list[index] != NULL) {
+            node = probe_list_find(INTERP, list[index], callback);
             
             if(node != NULL) {
-                probe_list_remove(INTERP, list[op_num], node);
+                probe_list_remove(INTERP, list[index], node);
             }
         }
+        
+        if(node == NULL) {
+            /* Callback was not found. */
+            Parrot_ex_throw_from_c_args(
+                INTERP, NULL, 1,
+                "Probe of '%S' not found in 'removal_op_hook'",
+                VTABLE_get_string(INTERP, id)
+            );
+        }
+    }
+
+/*
+=item C<INTVAL count_op_hooks(INTVAL op_num)>
+
+Returns the number of enabled op catchall probes.
+
+=cut
+*/
+
+    METHOD count_op_hooks (INTVAL op_num) {
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+        Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
+        probe_list_t         *list = core->op_hooks[op_num];
+        probe_node_t         *node = NULL;
+        INTVAL               count = 0;
+        
+        node = (list != NULL) ? list->head : NULL;
+        while(node != NULL) {
+            count++;
+            node = node->next;
+        }
+        
+        RETURN(INTVAL count);
     }
 
 /*
@@ -373,7 +426,7 @@
     }
 
 /*
-=item C<void *remove_op_catchall(PMC *id)>
+=item C<void *remove_op_catchall(PMC *id, PMC *callback)>
 
 Deregister a catchall op callback
 
@@ -388,10 +441,43 @@
         
         node = probe_list_find(INTERP, list, callback);
         
+        if(node == NULL) {
+            /* Callback was not found. */
+            Parrot_ex_throw_from_c_args(
+                INTERP, NULL, 1,
+                "Probe of '%S' not found in 'removal_op_hook'",
+                VTABLE_get_string(INTERP, id)
+            );
+        }
+        
         probe_list_remove(INTERP, list, node);
     }
 
 /*
+=item C<INTVAL count_op_catchalls()>
+
+Returns the number of enabled op catchall probes.
+
+=cut
+*/
+
+    METHOD count_op_catchalls () {
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+        Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
+        probe_list_t         *list = core->op_catchall;
+        probe_node_t         *node = NULL;
+        INTVAL               count = 0;
+        
+        node = list->head;
+        while(node != NULL) {
+            count++;
+            node = node->next;
+        }
+        
+        RETURN(INTVAL count);
+    }
+
+/*
 =item C<PMC *get_op_arg(INTVAL arg, INTVAL arg_type)>
 
 Interprets arg according to arg_type and returns the value as a PMC.
@@ -419,51 +505,51 @@
             break;
           case PARROT_ARG_I:
             ret = Parrot_pmc_new(INTERP, enum_class_Integer);
-            VTABLE_set_integer_native(INTERP, ret, *Parrot_pcc_get_INTVAL_reg(INTERP, cc, arg));
+            VTABLE_set_integer_native(INTERP, ret, *Parrot_pcc_get_INTVAL_reg(attr->supervised, cc, arg));
 
             break;
           case PARROT_ARG_NC:
             ret = Parrot_pmc_new(INTERP, enum_class_Float);
-            VTABLE_set_number_native(INTERP, ret, Parrot_pcc_get_num_constant_func(INTERP, cc, arg));
+            VTABLE_set_number_native(INTERP, ret, Parrot_pcc_get_num_constant_func(attr->supervised, cc, arg));
             
             break;
           case PARROT_ARG_N:
             ret = Parrot_pmc_new(INTERP, enum_class_Float);
-            VTABLE_set_number_native(INTERP, ret, *Parrot_pcc_get_FLOATVAL_reg(INTERP, cc, arg));
+            VTABLE_set_number_native(INTERP, ret, *Parrot_pcc_get_FLOATVAL_reg(attr->supervised, cc, arg));
 
             break;
           case PARROT_ARG_PC:
-            ret = Parrot_pcc_get_pmc_constant_func(INTERP, cc, arg);
+            ret = Parrot_pcc_get_pmc_constant_func(attr->supervised, cc, arg);
             
             break;
           case PARROT_ARG_P:
-            ret = *Parrot_pcc_get_PMC_reg(INTERP, cc, arg);
+            ret = *Parrot_pcc_get_PMC_reg(attr->supervised, cc, arg);
             
             break;
           case PARROT_ARG_SC:
             ret = Parrot_pmc_new(INTERP, enum_class_String);
-            VTABLE_set_string_native(INTERP, ret, Parrot_pcc_get_string_constant_func(INTERP, cc, arg));
+            VTABLE_set_string_native(INTERP, ret, Parrot_pcc_get_string_constant_func(attr->supervised, cc, arg));
             
             break;
           case PARROT_ARG_S:
             ret = Parrot_pmc_new(INTERP, enum_class_String);
-            VTABLE_set_string_native(INTERP, ret, *Parrot_pcc_get_STRING_reg(INTERP, cc, arg));
+            VTABLE_set_string_native(INTERP, ret, *Parrot_pcc_get_STRING_reg(attr->supervised, cc, arg));
 
             break;
           case PARROT_ARG_K:
             /* Key is PMC */
-            ret = *Parrot_pcc_get_PMC_reg(INTERP, cc, arg);
+            ret = *Parrot_pcc_get_PMC_reg(attr->supervised, cc, arg);
             
             break;
           case PARROT_ARG_KC:
             /* Key is String reg or String const */
-            ret = (Parrot_pcc_get_constants(INTERP, cc)[arg])->u.key;
+            ret = (Parrot_pcc_get_constants(attr->supervised, cc)[arg])->u.key;
 
             break;
           case PARROT_ARG_KI:
             /* Key is integer reg */
             ret = Parrot_pmc_new(INTERP, enum_class_Integer);
-            VTABLE_set_integer_native(INTERP, ret, *Parrot_pcc_get_INTVAL_reg(INTERP, cc, arg));
+            VTABLE_set_integer_native(INTERP, ret, *Parrot_pcc_get_INTVAL_reg(attr->supervised, cc, arg));
             
             break;
           case PARROT_ARG_KIC:
@@ -517,6 +603,13 @@
             supervisor->op_info_table = interp->op_info_table;
         }
         
+        if((pc - interp->code->base.data) == 45) {
+            PMC *mro, *def;
+            
+            //mro = 
+            //printf("%d\n");
+        }
+        
         Instrument_fire_hooks(pc, interp);
         DO_OP(pc, interp);
         
@@ -632,6 +725,7 @@
     cur_probe = (op_catchalls != NULL) ? op_catchalls->head : NULL;
     while(cur_probe != NULL || !done_catchalls) {
         PMC *callback;
+        probe_node_t *next;
     
         /* Switch to the specific probes if we are done with catchalls. */
         if(cur_probe == NULL && !done_catchalls) {
@@ -639,15 +733,15 @@
             done_catchalls = 1;
             continue;
         }
-        
+
         /* Fire the probe. */
         callback = cur_probe->list_obj;
+        next     = cur_probe->next;
         
         if(!PMC_IS_NULL(callback)) {
             Parrot_ext_call(supervisor, callback, "IPP->", pc_relative, op_data, instrument);
         }
-        
-        cur_probe = cur_probe->next;
+        cur_probe = next;
     }
     
     /* Done */
@@ -666,7 +760,8 @@
     
     list = mem_gc_allocate_zeroed_typed(interp, probe_list_t);
     
-    list->head = list->tail = NULL;
+    list->head = NULL;
+    list->tail = NULL;
     
     return list;
 }
@@ -690,10 +785,6 @@
  * Deletes the node.
  */
 static void probe_list_delete_node (PARROT_INTERP, probe_node_t *node) {
-    node->prev->next = node->next;
-    node->next->prev = node->prev;
-    
-    node->next = node->prev = NULL;
 
     mem_gc_free(interp, node);
 }
@@ -745,6 +836,16 @@
 static PMC * probe_list_remove (PARROT_INTERP, probe_list_t *list, probe_node_t *node) {
     PMC *item;
     
+    if(node == list->head) {
+        list->head = node->next;
+    }
+    if(node == list->tail) {
+        list->tail = node->prev;
+    }
+    
+    if(node->prev != NULL) { node->prev->next = node->next; }
+    if(node->next != NULL) { node->next->prev = node->prev; }
+    
     item = node->list_obj;
     
     probe_list_delete_node(interp, node);

Modified: branches/gsoc_instrument/t/dynpmc/instrument.t
==============================================================================
--- branches/gsoc_instrument/t/dynpmc/instrument.t	Sat Jun  5 11:34:24 2010	(r47380)
+++ branches/gsoc_instrument/t/dynpmc/instrument.t	Sat Jun  5 12:10:02 2010	(r47381)
@@ -19,10 +19,12 @@
 .sub main :main
     .include 'test_more.pir'
 
-    plan(5)
+    plan(18)
     test_loadlib()
     test_instantiate()
     test_attach()
+    test_insert_and_remove_op_hook()
+    test_insert_and_remove_op_catchall()
     
     .return()
 .end
@@ -48,18 +50,155 @@
 .end
 
 .sub 'test_attach'    
-    .local pmc mock_probe, mock_id, instr
-    .local pmc class, enable_method, ins, it, type
+    .local pmc mock_probe, instr
     
-    mock_id    = box 'MockProbe-0'
     mock_probe = new ['MockProbe']
-    setattribute mock_probe, '$!identifier', mock_id
     
     instr      = new ['Instrument']
     instr.'attach'(mock_probe)
     
 .end
 
+.sub 'test_insert_and_remove_op_hook'
+    # Plan: Test insertion and removal of hooks.
+    .local pmc instr
+    .local pmc stub1, stub2, fake_id
+    
+    fake_id = box 'FakeProbeId'
+    stub1   = get_global 'stub_1'
+    stub2   = get_global 'stub_2'
+    
+    instr = new ['Instrument']
+
+    # Test insert and remove 1 hook on existing op (op 0 = noop).
+    instr.'insert_op_hook'(fake_id, 0, stub1)
+    $I0 = instr.'count_op_hooks'(0)
+    is($I0, 1, 'Insertion successful')
+    
+    instr.'remove_op_hook'(fake_id, 0, stub1)
+    $I0 = instr.'count_op_hooks'(0)
+    is($I0, 0, 'Removal successful')
+    
+    # Test insert and removal 2 hooks on existing op.
+    instr.'insert_op_hook'(fake_id, 0, stub1)
+    instr.'insert_op_hook'(fake_id, 0, stub2)
+    $I0 = instr.'count_op_hooks'(0)
+    is($I0, 2, 'Insertion successful')
+    
+    instr.'remove_op_hook'(fake_id, 0, stub1)
+    $I0 = instr.'count_op_hooks'(0)
+    is($I0, 1, 'Removal of probe 1 successful')
+    
+    instr.'remove_op_hook'(fake_id, 0, stub2)
+    $I0 = instr.'count_op_hooks'(0)
+    is($I0, 0, 'Removal of probe 2 successful')
+    
+    # Test insertion on a non-existent op. (Say, op 5000)
+    .local pmc eh
+    eh = new ['ExceptionHandler']
+    set_addr eh, NON_EXIST_OP_OK
+    push_eh eh
+  
+    instr.'insert_op_hook'(fake_id, 5000, stub1)
+
+    ok(0, 'Managed to insert probe for non-existent op.')
+    goto NON_EXIST_OP_END
+    
+  NON_EXIST_OP_OK:
+    
+    ok(1, 'Detected non-existent op')
+    
+  NON_EXIST_OP_END:
+    
+    pop_eh
+  
+    # Test removal of non-existent hook.
+    eh = new ['ExceptionHandler']
+    set_addr eh, NON_EXIST_PROBE_OK
+    push_eh eh
+  
+    instr.'remove_op_hook'(fake_id, 0, stub1)
+
+    ok(0, 'Managed to remove non-existent probe.')
+    goto NON_EXIST_PROBE_END
+    
+  NON_EXIST_PROBE_OK:
+    
+    ok(1, 'Detected non-existent probe')
+    
+  NON_EXIST_PROBE_END:
+    
+    pop_eh
+    
+.end
+
+.sub 'test_insert_and_remove_op_catchall'
+    # Plan: Test insertion and removal of catchall probes.
+    .local pmc instr
+    .local pmc stub1, stub2, fake_id
+    
+    fake_id = box 'FakeCatchallProbeId'
+    stub1   = get_global 'stub_1'
+    stub2   = get_global 'stub_2'
+    
+    instr = new ['Instrument']
+
+    # Test insert and remove 1 catchall.
+    instr.'insert_op_catchall'(fake_id, stub1)
+    $I0 = instr.'count_op_catchalls'()
+    is($I0, 1, 'Insertion of catchall successful')
+    
+    instr.'remove_op_catchall'(fake_id, stub1)
+    $I0 = instr.'count_op_catchalls'()
+    is($I0, 0, 'Removal of catchall successful')
+    
+    # Test insert and removal 2 catchalls.
+    instr.'insert_op_catchall'(fake_id, stub1)
+    instr.'insert_op_catchall'(fake_id, stub2)
+    $I0 = instr.'count_op_catchalls'()
+    is($I0, 2, 'Insertion of catchalls successful')
+    
+    instr.'remove_op_catchall'(fake_id, stub1)
+    $I0 = instr.'count_op_catchalls'()
+    is($I0, 1, 'Removal of catchall probe 1 successful')
+    
+    instr.'remove_op_catchall'(fake_id, stub2)
+    $I0 = instr.'count_op_catchalls'()
+    is($I0, 0, 'Removal of catchall probe 2 successful')
+  
+    # Test removal of non-existent catchall hook.
+    .local pmc eh
+    eh = new ['ExceptionHandler']
+    set_addr eh, NON_EXIST_CATCHALL_OK
+    push_eh eh
+  
+    instr.'remove_op_catchall'(fake_id, stub1)
+
+    ok(0, 'Managed to remove non-existent probe.')
+    goto NON_EXIST_CATCHALL_END
+    
+  NON_EXIST_CATCHALL_OK:
+    
+    ok(1, 'Detected non-existent probe')
+    
+  NON_EXIST_CATCHALL_END:
+    
+    pop_eh
+    
+.end
+
+
+# Stub callbacks to test insertion and removal.
+.sub 'stub_1'
+.end
+
+.sub 'stub_2'
+.end
+
+#
+# Simple Mock of Instrument::Probe to test
+#  attach.
+#
 .namespace ['MockProbe']
 .sub '' :anon :init :load
     .local pmc class
@@ -68,6 +207,12 @@
     addattribute class, '$!identifier'
 .end
 
+.sub 'init' :vtable :method
+    $P0 = new ['String']
+    $P0 = 'MockProbe-0'
+    setattribute self, '$!identifier', $P0
+.end
+
 .sub 'enable' :method
     ok(1, 'Enable is called')
     
@@ -83,6 +228,9 @@
     .return()
 .end
 
+.sub 'disable' :method
+.end
+
 # Local Variables:
 #   mode: pir
 #   fill-column: 100


More information about the parrot-commits mailing list