[nemiver] Tie life time of IDebugger::Variable and varobjs
- From: Dodji Seketeli <dodji src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nemiver] Tie life time of IDebugger::Variable and varobjs
- Date: Fri, 23 Dec 2011 16:18:15 +0000 (UTC)
commit 0b9b09981c2f661ae99668375da85042257972a2
Author: Dodji Seketeli <dodji seketeli org>
Date: Sun Dec 11 17:08:51 2011 +0100
Tie life time of IDebugger::Variable and varobjs
* src/dbgengine/nmv-i-debugger.h (IDebugger::delete_variable): Add
an overload declaration that takes the internal name of the
backend-side variable object to delete. Add comments to all the
overloads.
(IDebugger::DefaultSlot): Move typedef before declaration of
IDebugger::Variable.
(IDebugger::Variable::m_debugger): New member.
(IDebubber::Variable::Variable): Adjust constructors to initialize
the new m_debugger member.
(IDebugger::Variable::debugger): New accessor.
(IDebugger::Variable::~Variable): If the debugging engine is still
connected to the Delete the backend-side variable
object if any.
(IDebugger::variable_deleted_signal): Add comments.
* src/dbgengine/nmv-gdb-engine.h (GDBEngine::delete_variable):
Declare new overload.
* src/dbgengine/nmv-gdb-engine.cc
(OnCreateVariableHandler::do_handle): Associate the instance of
IDebugger::Variable with the instance of IDebugger::Variable it
was created from, iff there is backend-side variable object for
that variable.
(OnDeleteVariableHandler::do_handle): Some requests for deleting
variable can have null instances of IDebugger::Variable
associated. Handle those.
(GDBEngine::delete_variable): Implement the new overload to delete
a variable object from its "internal name". Add comments to the
other overloads.
* src/dbgengine/nmv-varobj-walker.cc (~VarobjWalker): Remove.
(delete_varobj_if_necessary): Remove.
(connect): Remove call to delete_varobj_if_necessary.
* src/persp/dbgperspective/nmv-local-vars-inspector.cc
(LocalVarsInspector::Priv::clear_local_variables)
(LocalVarsInspector::Priv::clear_function_arguments): Remove uses
of delete_vars_backend_peers.
(LocalVarsInspector::Priv::delete_vars_backend_peers): Remove.
* src/persp/dbgperspective/nmv-var-inspector.cc
(VarInspector::Priv::graphically_set_variable)
(VarInspector::Priv::~Priv, VarInspector::inspect_variable)
(VarInspector::clear): Remove use of delete_variable_if_needed.
(VarInspector::Priv::delete_variable_if_needed): Remove.
* tests/fooprog.cc (main): Don't name unused parameters.
* tests/test-var-path-expr.cc (variables): New global
container of variables.
(on_variable_deleted_signal): New signal handler.
(on_breakpoints_set_signal): Clear variables instead of quitting
the event loop.
(on_variable_unfolded, on_variable_created): Add the variable to
the "variables" container.
(on_stopped_signal): Count the number of variable created.
Avoid needlessly passing a reference to the debugger engine.
(test_main): Don't name unused arguments. Handle the
IDebugger::variable_deleted_signal event.
* tests/test-var-walker.cc (VariableList): Rename
DebuggerVariableList into this.
(variables): New global variable to hold variables.
(on_frames_arguments_listed_signal, on_local_variables_listed_signal):
Don't name unused parameters. Add function arguments to the
"variables" global.
(test_main): Adjust b/c fooprog's main function doesn't have any
named parameter anymore. Clear the "variables" global after the
event loop is closed.
* tests/test-vars.cc (variables): New global to handle variables.
(person_var): Rename var_to_delete into this.
(on_variable_created_signal, on_varible_created_signal2): Add
variable to the "variables" global.
(on_changed_variables_listed_signal): Don't explicitly
delete_variable anymore. Keep stepping, and don't hold a
reference on the person_var reference.
(on_variable_deleted_signal, on_variable_deleted_signal2): Be
aware that a_var can be empty for backend-side variable objects.
(on_stopped_signal): Adjust.
(test_main): Don't expect any variable to be have been deleted
during this test, and clear the "variables" global.
src/dbgengine/nmv-gdb-engine.cc | 88 +++++++++++++--
src/dbgengine/nmv-gdb-engine.h | 4 +
src/dbgengine/nmv-i-debugger.h | 120 +++++++++++++++++--
src/dbgengine/nmv-varobj-walker.cc | 25 ----
.../dbgperspective/nmv-local-vars-inspector.cc | 15 ---
src/persp/dbgperspective/nmv-var-inspector.cc | 18 ---
tests/fooprog.cc | 3 +-
tests/test-var-path-expr.cc | 46 +++++++-
tests/test-var-walker.cc | 35 ++++--
tests/test-vars.cc | 57 ++++++---
10 files changed, 295 insertions(+), 116 deletions(-)
---
diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index b9b7436..3d44c07 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -2735,6 +2735,8 @@ struct OnCreateVariableHandler : public OutputHandler
void do_handle (CommandAndOutput &a_in)
{
VariableSafePtr var = a_in.output ().result_record ().variable ();
+ if (!var->internal_name ().empty ())
+ var->debugger (m_engine);
// Set the name of the variable to the name that got stored
// in the tag0 member of the command.
@@ -2785,20 +2787,30 @@ struct OnDeleteVariableHandler : public OutputHandler {
void do_handle (CommandAndOutput &a_in)
{
- THROW_IF_FAIL (a_in.command ().variable ());
+ IDebugger::VariableSafePtr var;
THROW_IF_FAIL (m_engine);
- // Call the slot associated to IDebugger::delete_variable (), if
- // Any.
+ // Call the slot associated to IDebugger::delete_variable (),
+ // if Any.
if (a_in.command ().has_slot ()) {
- typedef sigc::slot<void, const IDebugger::VariableSafePtr> SlotType;
- SlotType slot = a_in.command ().get_slot<SlotType> ();
- slot (a_in.command ().variable ());
+ // The resulting command can either have an associated
+ // instance of IDebugger::Variable attached to it or not,
+ // depending on the flavor of IDebugger::delete_variable
+ // that was called. Make sure to handle both cases.
+ if (a_in.command ().variable ()) {
+ typedef sigc::slot<void, const IDebugger::VariableSafePtr> SlotType;
+ SlotType slot = a_in.command ().get_slot<SlotType> ();
+ var = a_in.command ().variable ();
+ slot (var);
+ } else {
+ typedef IDebugger::DefaultSlot DefaultSlot;
+ IDebugger::DefaultSlot slot = a_in.command ().get_slot<DefaultSlot> ();
+ slot ();
+ }
}
// Emit the general IDebugger::variable_deleted_signal ().
- m_engine->variable_deleted_signal ().emit
- (a_in.command ().variable (),
- a_in.command ().cookie ());
+ m_engine->variable_deleted_signal ().emit (var,
+ a_in.command ().cookie ());
}
}; // end OnDeleteVariableHandler
@@ -5755,6 +5767,19 @@ GDBEngine::create_variable (const UString &a_name,
queue_command (command);
}
+/// If a variable has a GDB variable object then this method deletes
+/// the backend. You should not use this method because the life
+/// cycle of variables backend counter parts is automatically tied to
+/// the life cycle of instances of IDebugger::Variable, unless you
+/// know what you are doing.
+///
+/// Note that when the varobj is deleted, the
+/// IDebugger::variable_deleted signal is invoked.
+///
+/// \param a_var the variable which backend counter to delete.
+///
+/// \param a_cookie a string cookie passed to the
+/// IDebugger::variable_deleted_signal.
void
GDBEngine::delete_variable (const VariableSafePtr a_var,
const UString &a_cookie)
@@ -5765,6 +5790,22 @@ GDBEngine::delete_variable (const VariableSafePtr a_var,
a_cookie);
}
+/// If a variable has a GDB variable object, then this method deletes
+/// the varobj. You should not use this method because the life cycle
+/// of variables backend counter parts is automatically tied to the
+/// life cycle of instances of IDebugger::Variable, unless you know
+/// what you are doing.
+///
+/// Note that when the varobj is deleted, the
+/// IDebugger::variable_deleted signal is invoked.
+///
+/// \param a_var the variable which backend counter to delete.
+///
+/// \param a_slot a slot asynchronously called when the backend
+/// variable oject is deleted.
+///
+/// \param a_cookie a string cookie passed to the
+/// IDebugger::variable_deleted_signal.
void
GDBEngine::delete_variable (const VariableSafePtr a_var,
const ConstVariableSlot &a_slot,
@@ -5783,6 +5824,35 @@ GDBEngine::delete_variable (const VariableSafePtr a_var,
queue_command (command);
}
+/// Deletes a variable object named by a given string. You should not
+/// use this method because the life cycle of variables backend
+/// counter parts is automatically tied to the life cycle of instances
+/// of IDebugger::Variable, unless you know what you are doing.
+///
+/// Note that when the backend counter part is deleted, the
+/// IDebugger::variable_deleted signal is invoked.
+///
+/// \param a_internal_name the name of the backend variable object we
+/// want to delete.
+///
+/// \param a_slot a slot that is going to be called asynchronuously
+/// when the backend object is deleted.
+void
+GDBEngine::delete_variable (const UString &a_internal_name,
+ const DefaultSlot &a_slot,
+ const UString &a_cookie)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ THROW_IF_FAIL (!a_internal_name.empty ());
+
+ Command command ("delete-variable",
+ "-var-delete " + a_internal_name,
+ a_cookie);
+ command.set_slot (a_slot);
+ queue_command (command);
+}
+
/// Unfold a given variable.
///
/// Query the backend for the member variables of the given variable.
diff --git a/src/dbgengine/nmv-gdb-engine.h b/src/dbgengine/nmv-gdb-engine.h
index 11b1668..cea76ed 100644
--- a/src/dbgengine/nmv-gdb-engine.h
+++ b/src/dbgengine/nmv-gdb-engine.h
@@ -584,6 +584,10 @@ public:
const ConstVariableSlot &a_s,
const UString &a_cookie);
+ void delete_variable (const UString &a_internal_name,
+ const DefaultSlot &a_slot,
+ const UString &a_cookie);
+
void unfold_variable (VariableSafePtr a_var,
const UString &a_cookie);
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index 6fb5fff..56bea4a 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -345,6 +345,8 @@ public:
m_args.clear ();
}
};//end class Frame
+
+ typedef sigc::slot<void> DefaultSlot;
typedef sigc::slot<void, const vector<IDebugger::Frame>&>
FrameVectorSlot;
typedef sigc::slot<void, const map<int, IDebugger::VariableList>& >
@@ -378,6 +380,14 @@ public:
// (e.g: backend side variable objects in GDB), then this
// is the name of the backend side counterpart of this variable.
UString m_internal_name;
+ // If the variable was created with a backend counterpart
+ // (e.g, GDB Variable objects), then this client-side
+ // variable instance needs to have a hold on the instance of
+ // IDebugger that was used to create the variable. This is
+ // needed so that that instance of IDebugger can be used to
+ // tie the life cycle of the remote variable object peer with
+ // the life cycle of this instance.
+ mutable IDebugger *m_debugger;
UString m_name;
UString m_name_caption;
UString m_value;
@@ -412,8 +422,10 @@ public:
const UString &a_name,
const UString &a_value,
const UString &a_type,
- bool a_in_scope = true)
+ bool a_in_scope = true,
+ IDebugger *a_dbg = 0)
: m_internal_name (a_internal_name),
+ m_debugger (a_dbg),
m_name (a_name),
m_value (a_value),
m_type (a_type),
@@ -428,8 +440,10 @@ public:
Variable (const UString &a_name,
const UString &a_value,
const UString &a_type,
- bool a_in_scope = true)
- : m_name (a_name),
+ bool a_in_scope = true,
+ IDebugger *a_dbg = 0)
+ : m_debugger (a_dbg),
+ m_name (a_name),
m_value (a_value),
m_type (a_type),
m_parent (0),
@@ -441,24 +455,41 @@ public:
{
}
- Variable (const UString &a_name)
- : m_name (a_name),
+ Variable (const UString &a_name,
+ IDebugger *a_dbg = 0)
+ : m_debugger (a_dbg),
+ m_name (a_name),
m_parent (0),
m_num_expected_children (0),
m_in_scope (true),
m_format (UNDEFINED_FORMAT),
m_needs_revisualizing (false)
-
- {}
+ {
+ }
- Variable ()
- : m_parent (0),
+ Variable (IDebugger *a_dbg = 0)
+ : m_debugger (a_dbg),
+ m_parent (0),
m_num_expected_children (0),
m_in_scope (true),
m_format (UNDEFINED_FORMAT),
m_needs_revisualizing (false)
-
- {}
+ {
+ }
+
+ ~Variable ()
+ {
+ // If this variable is peered with an engine-side variable
+ // object then ask the debugging engine to delete the peer
+ // variable object now.
+ if (m_debugger
+ && !internal_name ().empty ()
+ && m_debugger->is_attached_to_target ()) {
+ IDebugger::DefaultSlot empty_slot;
+ m_debugger->delete_variable (internal_name (),
+ empty_slot);
+ }
+ }
const VariableList& members () const {return m_members;}
@@ -552,6 +583,10 @@ public:
/// \param a_in the new name of backend side counterpart variable object.
void internal_name (const UString &a_in) {m_internal_name = a_in;}
+
+ IDebugger* debugger () const {return m_debugger;}
+ void debugger (IDebugger *a_dbg) {m_debugger = a_dbg;}
+
const UString& name () const {return m_name;}
void name (const UString &a_name)
{
@@ -871,8 +906,6 @@ public:
return false;
}
- typedef sigc::slot<void> DefaultSlot;
-
typedef sigc::slot<void,
const std::pair<int, const IDebugger::Breakpoint&>&>
BreakpointSlot;
@@ -1086,6 +1119,12 @@ public:
virtual sigc::signal<void, const VariableSafePtr, const UString&>&
variable_created_signal () const = 0;
+ /// This signal is emitted after IDebugger::delete_variable is
+ /// called and the underlying backend-side variable object has
+ /// been effectively deleted. Note that when no instance of
+ /// VariableSafePtr has been passed to the
+ /// IDebugger::delete_variable method, the first argument of this
+ /// signal slot is a null pointer to VariableSafePtr.
virtual sigc::signal<void, const VariableSafePtr, const UString&>&
variable_deleted_signal () const = 0;
@@ -1386,13 +1425,68 @@ public:
const ConstVariableSlot &a_slot,
const UString &a_cookie = "") = 0;
+ /// If a variable has a backend counterpart (e.g, a variable object
+ /// when using the GDB backend), then this method deletes the
+ /// backend. You should not use this method because the life cycle
+ /// of variables backend counter parts is automatically
+ /// tied to the life cycle of instances of IDebugger::Variable,
+ /// unless you know what you are doing.
+ ///
+ /// Note that when the backend counter part is deleted, the
+ /// IDebugger::variable_deleted_signal is invoked with the a_var
+ /// variable in argument.
+ ///
+ /// \param a_var the variable which backend counter to delete.
+ ///
+ /// \param a_cookie a string cookie passed to the
+ /// IDebugger::variable_deleted_signal.
virtual void delete_variable (const VariableSafePtr a_var,
const UString &a_cookie = "") = 0;
+ /// If a variable has a backend counterpart (e.g, a variable object
+ /// when using the GDB backend), then this method deletes the
+ /// backend. You should not use this method because the life cycle
+ /// of variables backend counter parts is automatically
+ /// tied to the life cycle of instances of IDebugger::Variable,
+ /// unless you know what you are doing.
+ ///
+ /// Note that when the backend counter part is deleted, the
+ /// IDebugger::variable_deleted_signal is invoked with the a_var
+ /// variable in argument.
+ ///
+ /// \param a_var the variable which backend counter to delete.
+ ///
+ /// \param a_slot a slot asynchronously called when the backend
+ /// variable oject is deleted.
+ ///
+ /// \param a_cookie a string cookie passed to the
+ /// IDebugger::variable_deleted_signal.
virtual void delete_variable (const VariableSafePtr a_var,
const ConstVariableSlot&,
const UString &a_cookie = "") = 0;
+ /// Deletes a backend variable object (e.g, for GDB, a so called
+ /// variable object) named by a given string.
+ /// You should not use this method because the life cycle
+ /// of variables backend counter parts is automatically
+ /// tied to the life cycle of instances of IDebugger::Variable,
+ /// unless you know what you are doing.
+ ///
+ /// Note that when the backend counter part is deleted, the
+ /// IDebugger::variable_deleted_signal is invoked, with null pointer
+ /// to IDebugger::Variable.
+ ///
+ /// \param a_internal_name the name of the backend variable object
+ /// we want to delete.
+ ///
+ /// \param a_slot a slot that is going to be called
+ /// asynchronuously when the backend object is deleted.
+ ///
+ /// \param a_cookie
+ virtual void delete_variable (const UString &a_internal_name,
+ const DefaultSlot &a_slot,
+ const UString &a_cookie = "") = 0;
+
virtual void unfold_variable (VariableSafePtr a_var,
const UString &a_cookie = "") = 0;
virtual void unfold_variable
diff --git a/src/dbgengine/nmv-varobj-walker.cc b/src/dbgengine/nmv-varobj-walker.cc
index 462b3b5..9fab8f1 100644
--- a/src/dbgengine/nmv-varobj-walker.cc
+++ b/src/dbgengine/nmv-varobj-walker.cc
@@ -73,11 +73,6 @@ public:
{
}
- ~VarobjWalker ()
- {
- delete_varobj_if_necessary ();
- }
-
sigc::signal<void,
const IDebugger::VariableSafePtr>
visited_variable_node_signal () const;
@@ -101,8 +96,6 @@ public:
unsigned get_maximum_member_depth () const;
- void delete_varobj_if_necessary ();
-
void do_walk_variable_real (const IDebugger::VariableSafePtr,
unsigned a_max_depth);
@@ -135,8 +128,6 @@ VarobjWalker::connect (IDebuggerSafePtr a_debugger,
THROW_IF_FAIL (a_debugger);
THROW_IF_FAIL (!a_var_name.empty ());
- delete_varobj_if_necessary ();
-
m_debugger = a_debugger;
m_var_name = a_var_name;
m_debugger->create_variable
@@ -156,8 +147,6 @@ VarobjWalker::connect (IDebuggerSafePtr a_debugger,
// The variable must be backed by variable objects.
THROW_IF_FAIL (!a_var->internal_name ().empty ());
- delete_varobj_if_necessary ();
-
m_debugger = a_debugger;
m_variable = a_var;
}
@@ -213,20 +202,6 @@ VarobjWalker::get_maximum_member_depth () const
}
void
-VarobjWalker::delete_varobj_if_necessary ()
-{
- LOG_FUNCTION_SCOPE_NORMAL_DD;
-
- if (!m_var_name.empty ()
- && m_variable
- && m_debugger
- && m_debugger->is_attached_to_target ()) {
- m_debugger->delete_variable (m_variable);
- }
-
-}
-
-void
VarobjWalker::do_walk_variable_real (const IDebugger::VariableSafePtr a_var,
unsigned a_max_depth)
{
diff --git a/src/persp/dbgperspective/nmv-local-vars-inspector.cc b/src/persp/dbgperspective/nmv-local-vars-inspector.cc
index 05659c3..e1c222c 100644
--- a/src/persp/dbgperspective/nmv-local-vars-inspector.cc
+++ b/src/persp/dbgperspective/nmv-local-vars-inspector.cc
@@ -329,7 +329,6 @@ public:
row_it = tree_store->erase (row_it);
}
}
- delete_vars_backend_peers (local_vars);
local_vars.clear ();
local_vars_changed_at_prev_stop.clear ();
}
@@ -347,7 +346,6 @@ public:
row_it = tree_store->erase (*row_it);
}
}
- delete_vars_backend_peers (function_arguments);
function_arguments.clear ();
func_args_changed_at_prev_stop.clear ();
}
@@ -591,19 +589,6 @@ public:
}
}
- void
- delete_vars_backend_peers (IDebugger::VariableList &a_vars)
- {
- for (IDebugger::VariableList::const_iterator it = a_vars.begin ();
- it != a_vars.end ();
- ++it) {
- if (!(*it) || (*it)->internal_name ().empty ()) {
- continue;
- }
- debugger->delete_variable (*it);
- }
- }
-
Glib::RefPtr<Gtk::UIManager>
get_ui_manager ()
{
diff --git a/src/persp/dbgperspective/nmv-var-inspector.cc b/src/persp/dbgperspective/nmv-var-inspector.cc
index c95ad97..d5f109f 100644
--- a/src/persp/dbgperspective/nmv-var-inspector.cc
+++ b/src/persp/dbgperspective/nmv-var-inspector.cc
@@ -163,20 +163,6 @@ class VarInspector::Priv : public sigc::trackable {
get_ui_manager ()->insert_action_group (var_inspector_action_group);
}
- // If the variable we are inspected was created
- // with a backend counterpart (variable objects for GDB),
- // instruct the backend to delete its variable counterpart.
- void
- delete_variable_if_needed ()
- {
- LOG_FUNCTION_SCOPE_NORMAL_DD;
- if (variable
- && !variable->internal_name ().empty ()
- && debugger) {
- debugger->delete_variable (variable);
- }
- }
-
void
graphically_set_variable (const IDebugger::VariableSafePtr a_variable,
bool a_expand)
@@ -213,7 +199,6 @@ class VarInspector::Priv : public sigc::trackable {
re_visualize = a_re_visualize;
re_init_tree_view ();
- delete_variable_if_needed ();
variable = a_variable;
if (a_re_visualize) {
debugger->revisualize_variable (a_variable,
@@ -629,7 +614,6 @@ public:
~Priv ()
{
- delete_variable_if_needed ();
}
};//end class VarInspector::Priv
@@ -670,7 +654,6 @@ VarInspector::inspect_variable (const UString &a_variable_name,
if (a_variable_name == "") {return;}
THROW_IF_FAIL (m_priv);
m_priv->re_init_tree_view ();
- m_priv->delete_variable_if_needed ();
m_priv->create_variable (a_variable_name, a_expand);
}
@@ -701,7 +684,6 @@ VarInspector::clear ()
{
THROW_IF_FAIL (m_priv);
m_priv->re_init_tree_view ();
- m_priv->delete_variable_if_needed ();
}
NEMIVER_END_NAMESPACE (nemiver)
diff --git a/tests/fooprog.cc b/tests/fooprog.cc
index 61bdb96..b2a8900 100644
--- a/tests/fooprog.cc
+++ b/tests/fooprog.cc
@@ -92,8 +92,7 @@ func4 (Person &a_person)
}
int
-main (int a_argc __attribute__((unused)),
- char *a_argv[] __attribute__((unused)))
+main (int, char **)
{
Person person ("Bob", "Barton", 15);
func1 ();
diff --git a/tests/test-var-path-expr.cc b/tests/test-var-path-expr.cc
index f215c36..34063cf 100644
--- a/tests/test-var-path-expr.cc
+++ b/tests/test-var-path-expr.cc
@@ -11,6 +11,15 @@
using namespace nemiver;
using namespace nemiver::common;
+typedef std::list<IDebugger::VariableSafePtr> VariablesList;
+
+static int num_variables_created;
+
+// This container holds variables backed up by backend-side
+// variable objects created during this test, so that they stay
+// alive during the life of this test.
+VariablesList variables;
+
Glib::RefPtr<Glib::MainLoop> loop =
Glib::MainLoop::create (Glib::MainContext::get_default ());
@@ -28,6 +37,23 @@ on_program_finished_signal ()
loop->quit ();
}
+/// Counts the number of deleted variables. If it equals the number
+/// of created variables, then exit the event loop, effectively
+/// allowing the test to exit.
+static void
+on_variable_deleted_signal (const IDebugger::VariableSafePtr a_var,
+ const UString&)
+{
+ BOOST_REQUIRE (!a_var);
+ MESSAGE ("a backend-side variable object got deleted!");
+
+ static int num_variables_deleted;
+ num_variables_deleted++;
+
+ if (num_variables_deleted == num_variables_created)
+ loop->quit ();
+}
+
static void
on_breakpoints_set_signal (const std::map<int, IDebugger::Breakpoint> &a_breaks,
const UString &a_cookie)
@@ -49,7 +75,11 @@ on_variable_expr_path (const IDebugger::VariableSafePtr a_var)
MESSAGE ("var expr path: " << a_var->path_expression ());
BOOST_REQUIRE (a_var->path_expression ()
== "((((person).m_first_name)).npos)");
- loop->quit ();
+
+ // This should help delete all the variables (and their
+ // backend-side variable objects) created during this test, along
+ // with a_var, after this function returns.
+ variables.clear ();
}
static void
@@ -68,6 +98,8 @@ on_variable_unfolded (const IDebugger::VariableSafePtr a_var,
a_debugger->query_variable_path_expr (a_var->members ().front (),
&on_variable_expr_path);
}
+ // Ensure that a_var lives throughout the test.
+ variables.push_back (a_var);
}
static void
@@ -76,6 +108,9 @@ on_variable_created (const IDebugger::VariableSafePtr a_var,
{
MESSAGE ("variable created: " << a_var->name ());
+ // Add a_var to the list of live variables, so that it remains
+ // alive during the whole life of the main function.
+ variables.push_back (a_var);
if (a_var->needs_unfolding ()) {
MESSAGE ("unfolding variable " << a_var->name ());
a_debugger->unfold_variable (a_var,
@@ -91,7 +126,7 @@ on_stopped_signal (IDebugger::StopReason a_reason,
int /*a_thread_id*/,
int /*a_bp_num*/,
const UString &/*a_cookie*/,
- IDebuggerSafePtr &a_debugger)
+ IDebuggerSafePtr a_debugger)
{
MESSAGE ("stopped at: "
<< a_frame.function_name ()
@@ -104,16 +139,15 @@ on_stopped_signal (IDebugger::StopReason a_reason,
a_debugger->create_variable ("person",
sigc::bind (&on_variable_created,
a_debugger));
+ ++num_variables_created;
} else {
a_debugger->do_continue ();
}
}
NEMIVER_API int
-test_main (int argc, char *argv[])
+test_main (int, char **)
{
- if (argc || argv) {/*keep compiler happy*/}
-
NEMIVER_TRY
Initializer::do_init ();
@@ -133,6 +167,8 @@ test_main (int argc, char *argv[])
debugger->program_finished_signal ().connect
(&on_program_finished_signal);
+ debugger->variable_deleted_signal ().connect (&on_variable_deleted_signal);
+
debugger->breakpoints_list_signal ().connect
(&on_breakpoints_set_signal);
diff --git a/tests/test-var-walker.cc b/tests/test-var-walker.cc
index 11654de..768f3c8 100644
--- a/tests/test-var-walker.cc
+++ b/tests/test-var-walker.cc
@@ -12,14 +12,19 @@
using namespace nemiver;
using namespace nemiver::common;
+typedef std::list<IDebugger::VariableSafePtr> Variables;
+typedef std::map<std::string, IVarListWalkerSafePtr> VarListWalkerMap;
+typedef std::map<std::string, string> StringMap;
+
+// This is to hold variables which should live throughout the life
+// time of this test.
+Variables variables;
+
Glib::RefPtr<Glib::MainLoop> s_loop =
Glib::MainLoop::create (Glib::MainContext::get_default ());
IDebugger::Frame s_current_frame;
-typedef std::list<IDebugger::VariableSafePtr> DebuggerVariableList;
-typedef std::map<std::string, IVarListWalkerSafePtr> VarListWalkerMap;
-typedef std::map<std::string, string> StringMap;
VarListWalkerMap&
var_list_walker ()
@@ -123,15 +128,19 @@ on_stopped_signal (IDebugger::StopReason a_reason,
void
on_frames_arguments_listed_signal
(const map<int, list<IDebugger::VariableSafePtr> > &a_frames_params,
- const UString &a_cookie)
+ const UString &)
{
- if (a_cookie.empty ()) {/*keep compiler happy*/}
map<int, list<IDebugger::VariableSafePtr> >::const_iterator it;
it = a_frames_params.find (0);
if (it == a_frames_params.end ()) {
LOG_ERROR ("Could not find current frame");
return;
}
+ Variables::const_iterator i = it->second.begin ();
+ for (; i != it->second.end (); ++i) {
+ variables.push_back (*i);
+ }
+
BOOST_REQUIRE (var_list_walker ().find (s_current_frame.function_name ())
!= var_list_walker ().end ());
IVarListWalkerSafePtr walker = var_list_walker ()[s_current_frame.function_name ()];
@@ -142,13 +151,17 @@ on_frames_arguments_listed_signal
}
void
-on_local_variables_listed_signal (const DebuggerVariableList &a_variables,
- const UString &a_cookie)
+on_local_variables_listed_signal (const Variables &a_variables,
+ const UString &)
{
- if (a_variables.empty () || a_cookie.empty ()) {
- }
BOOST_REQUIRE (var_list_walker ().find (s_current_frame.function_name ())
!= var_list_walker ().end ());
+
+ Variables::const_iterator i = a_variables.begin ();
+ for (; i != a_variables.end (); ++i) {
+ variables.push_back (*i);
+ }
+
IVarListWalkerSafePtr walker = var_list_walker ()[s_current_frame.function_name ()];
BOOST_REQUIRE (walker);
walker->remove_variables ();
@@ -218,7 +231,7 @@ test_main (int argc, char **argv)
debugger->set_breakpoint ("func3");
var_list_walker ()["main"] = create_var_list_walker (debugger);
- expected_variables ()["main"] = " person a_argc a_argv";
+ expected_variables ()["main"] = " person";
var_list_walker ()["func1"] = create_var_list_walker (debugger);
expected_variables ()["func1"] = " i";
var_list_walker ()["func2"] = create_var_list_walker (debugger);
@@ -232,6 +245,8 @@ test_main (int argc, char **argv)
//****************************************
s_loop->run ();
+ variables.clear ();
+
BOOST_REQUIRE (actual_variables ().find ("main") != actual_variables ().end ());
BOOST_REQUIRE (actual_variables ().find ("func1") != actual_variables ().end ());
BOOST_REQUIRE (actual_variables ().find ("func2") != actual_variables ().end ());
diff --git a/tests/test-vars.cc b/tests/test-vars.cc
index b3f438f..bb1a017 100644
--- a/tests/test-vars.cc
+++ b/tests/test-vars.cc
@@ -12,6 +12,13 @@
using namespace nemiver;
using namespace nemiver::common;
+typedef std::list<IDebugger::VariableSafePtr> Variables;
+
+// This is to hold instances of IDebugger::Variable which backend-side
+// variable object has to live throughout the life time of this test.
+static Variables variables;
+static IDebugger::VariableSafePtr person_var;
+
Glib::RefPtr<Glib::MainLoop> s_loop =
Glib::MainLoop::create (Glib::MainContext::get_default ());
static int nb_vars_created;
@@ -19,7 +26,7 @@ static int nb_vars_created2;
static int nb_vars_deleted;
static int nb_vars_deleted2;
static int unfold_requests;
-static IDebugger::VariableSafePtr var_to_delete;
+
void on_variable_deleted_signal (const IDebugger::VariableSafePtr a_var);
void on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_var,
@@ -61,11 +68,12 @@ on_variable_created_signal (IDebugger::VariableSafePtr a_var)
a_var->to_string (var_str, true /*show var name*/);
MESSAGE ("variable created " << var_str);
+ variables.push_back (a_var);
nb_vars_created++;
if (a_var->name () == "person") {
// put the variable aside so that we
// can delete it later
- var_to_delete = a_var;
+ person_var = a_var;
}
}
@@ -77,6 +85,7 @@ on_variable_created_signal2 (IDebugger::VariableSafePtr a_var,
UString var_str;
a_var->to_string (var_str, true /*show var name*/);
MESSAGE ("variable created (second report): " << var_str);
+ variables.push_back (a_var);
nb_vars_created2++;
unfold_requests++;
@@ -166,16 +175,21 @@ on_changed_variables_listed_signal
MESSAGE ("name: " + (*it)->internal_name ());
MESSAGE ("value: " + (*it)->value ());
}
- a_debugger->delete_variable (root, &on_variable_deleted_signal);
+ a_debugger->step_over ();
+ person_var.reset ();
}
void
on_variable_deleted_signal (const IDebugger::VariableSafePtr a_var)
{
- MESSAGE ("variable deleted. Name: "
- << a_var->name ()
- << ", Internal Name: "
- << a_var->internal_name ());
+ if (a_var) {
+ MESSAGE ("variable deleted. Name: "
+ << a_var->name ()
+ << ", Internal Name: "
+ << a_var->internal_name ());
+ } else {
+ MESSAGE ("backend-side variable object deleted");
+ }
nb_vars_deleted++;
}
@@ -184,10 +198,14 @@ on_variable_deleted_signal2 (const IDebugger::VariableSafePtr a_var,
const UString&,
IDebuggerSafePtr a_debugger)
{
- MESSAGE ("variable deleted. Name: "
- << a_var->name ()
- << ", Internal Name: "
- << a_var->internal_name ());
+ if (a_var) {
+ MESSAGE ("variable deleted. Name: "
+ << a_var->name ()
+ << ", Internal Name: "
+ << a_var->internal_name ());
+ } else {
+ MESSAGE ("backend-side variable object deleted");
+ }
nb_vars_deleted2++;
a_debugger->step_over ();
}
@@ -219,13 +237,13 @@ on_stopped_signal (IDebugger::StopReason /*a_reason*/,
sigc::bind (&on_variable_created_in_func4_signal,
a_debugger));
} else if (nb_stops_in_func4 < 5 ) {
- a_debugger->step_over ("in-func4");
+ a_debugger->step_over ();
} else {
a_debugger->do_continue ();
}
} else if (nb_stops == 2) {
- // Okay we stepped once, now we can now create the variable
- // for the person variable.
+ // Okay we stepped once, we can now create the variable for
+ // the person variable.
a_debugger->create_variable ("person",
&on_variable_created_signal);
MESSAGE ("Requested creation of variable 'person'");
@@ -235,7 +253,7 @@ on_stopped_signal (IDebugger::StopReason /*a_reason*/,
// let's now ask the debugger to tell us which descendant variable
// was changed exactly.
a_debugger->list_changed_variables
- (var_to_delete,
+ (person_var,
sigc::bind (&on_changed_variables_listed_signal, a_debugger));
} else {
a_debugger->step_over ();
@@ -288,12 +306,13 @@ test_main (int, char **)
//****************************************
s_loop->run ();
- NEMIVER_CATCH_AND_RETURN_NOX (-1)
-
+ NEMIVER_CATCH_AND_RETURN_NOX (-1);
+
BOOST_REQUIRE (nb_vars_created == nb_vars_created2);
BOOST_REQUIRE (nb_vars_created > 0);
- BOOST_REQUIRE (nb_vars_deleted == nb_vars_deleted2);
- BOOST_REQUIRE (nb_vars_deleted > 0);
+ BOOST_REQUIRE (nb_vars_deleted == 0);
+
+ variables.clear ();
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]