[nemiver] New varobj aware variable walker
- From: Dodji Seketeli <dodji src gnome org>
- To: svn-commits-list gnome org
- Subject: [nemiver] New varobj aware variable walker
- Date: Sun, 31 May 2009 03:06:55 -0400 (EDT)
commit 59329f222e48d0a317a6804106f358fed97a1082
Author: Dodji Seketeli <dodji redhat com>
Date: Sat May 30 11:45:30 2009 +0200
New varobj aware variable walker
* configure.ac: Generate src/dbgengine/varobjwalker.conf from
src/dbgengine/varobjwalker.conf.in
* src/dbgengine/nmv-gdb-engine.cc:
(OnCreateVariableHandler::can_handle): Add more logging.
* src/dbgengine/nmv-i-var-walker.h: Cleanup the IVarWalker iface.
Remove some needless references from the APIs.
* src/dbgengine/nmv-var-walker.cc: Adjust API implementations.
* src/dbgengine/nmv-varobj-walker.cc: New implementation of
the IVarWalker interface. This one walks a variable that is backed
by GDB/MI a Variable Object and recursively unfolds it.
* src/dbgengine/Makefile.am: Add nmv-varobj-walker.cc to the build
system.
* src/dbgengine/varobjwalker.conf.in: The conf file of the
new varobjwalker DynMod.
* tests/test-varobj-walker.cc: New test for the varobj-walker.
* tests/Makefile.am: Add the new test-varobj-walker.cc to the build
system.
---
configure.ac | 1 +
src/dbgengine/Makefile.am | 18 +-
src/dbgengine/nmv-gdb-engine.cc | 2 +
src/dbgengine/nmv-i-var-walker.h | 16 +-
src/dbgengine/nmv-var-walker.cc | 40 ++--
src/dbgengine/nmv-varobj-walker.cc | 303 ++++++++++++++++++++
src/dbgengine/varobjwalker.conf.in | 10 +
.../dbgperspective/menus/varinspectorpopup.xml | 2 +
tests/Makefile.am | 10 +-
tests/test-varobj-walker.cc | 190 ++++++++++++
10 files changed, 560 insertions(+), 32 deletions(-)
diff --git a/configure.ac b/configure.ac
index 7de2564..63006ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -415,6 +415,7 @@ src/Makefile
src/dbgengine/cpptrait.conf
src/dbgengine/varlist.conf
src/dbgengine/varwalker.conf
+ src/dbgengine/varobjwalker.conf
src/dbgengine/varlistwalker.conf
src/confmgr/Makefile
src/confmgr/gconfmgr.conf
diff --git a/src/dbgengine/Makefile.am b/src/dbgengine/Makefile.am
index ad55059..06050d1 100644
--- a/src/dbgengine/Makefile.am
+++ b/src/dbgengine/Makefile.am
@@ -7,13 +7,19 @@ varlistmoddir= NEMIVER_MODULES_DIR@
varwalkermod_LTLIBRARIES=libvarwalkermod.la
varwalkermoddir= NEMIVER_MODULES_DIR@
+varobjwalkermod_LTLIBRARIES=libvarobjwalkermod.la
+varobjwalkermoddir= NEMIVER_MODULES_DIR@
+
varlistwalkermod_LTLIBRARIES=libvarlistwalkermod.la
varlistwalkermoddir= NEMIVER_MODULES_DIR@
cpptraitmod_LTLIBRARIES=libcpptraitmod.la
cpptraitmoddir= NEMIVER_MODULES_DIR@
-noinst_LTLIBRARIES=libgdbmiparser.la libdbgcommon.la libgdbengine.la
+noinst_LTLIBRARIES=\
+libgdbmiparser.la \
+libdbgcommon.la \
+libgdbengine.la
idebuggerheaders= \
nmv-i-debugger.h
@@ -46,6 +52,10 @@ libvarwalkermod_la_SOURCES= \
$(ivarwalkerheaders) \
nmv-var-walker.cc
+libvarobjwalkermod_la_SOURCES= \
+$(ivarwalkerheaders) \
+nmv-varobj-walker.cc
+
libvarlistwalkermod_la_SOURCES= \
$(ivarlistwalkerheaders) \
nmv-var-list-walker.cc
@@ -93,6 +103,10 @@ libvarwalkermod_la_LDFLAGS=-module -avoid-version
libvarwalkermod_la_LIBADD= NEMIVERCOMMON_LIBS@ \
$(top_builddir)/src/common/libnemivercommon.la
+libvarobjwalkermod_la_LDFLAGS=-module -avoid-version
+libvarobjwalkermod_la_LIBADD= NEMIVERCOMMON_LIBS@ \
+ $(top_builddir)/src/common/libnemivercommon.la
+
libvarlistwalkermod_la_LDFLAGS=-module -avoid-version
libvarlistwalkermod_la_LIBADD= NEMIVERCOMMON_LIBS@ \
$(top_builddir)/src/common/libnemivercommon.la
@@ -101,7 +115,7 @@ libgdbmiparser_la_LIBADD= \
@NEMIVERCOMMON_LIBS@ \
$(top_builddir)/src/common/libnemivercommon.la
-config_DATA=gdbengine.conf varlist.conf varwalker.conf varlistwalker.conf cpptrait.conf
+config_DATA=gdbengine.conf varlist.conf varwalker.conf varobjwalker.conf varlistwalker.conf cpptrait.conf
configdir= NEMIVER_SYSTEM_CONFIG_DIR@
INCLUDES= NEMIVERCOMMON_CFLAGS@ -DENABLE_NLS=1 -DDATADIR=\"${datadir}\" \
diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index 273c07e..b3068e8 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -2145,10 +2145,12 @@ struct OnCreateVariableHandler : public OutputHandler
// Call the slot associated to IDebugger::create_variable (), if
// any.
if (a_in.command ().has_slot ()) {
+ LOG_DD ("calling IDebugger::create_variable slot");
typedef sigc::slot<void, IDebugger::VariableSafePtr> SlotType;
SlotType slot = a_in.command ().get_slot<SlotType> ();
slot (a_in.output ().result_record ().variable ());
}
+ LOG_DD ("emit IDebugger::variable_create_signal");
// Emit the general IDebugger::variable_create_signal () signal
m_engine->variable_created_signal ().emit
(a_in.output ().result_record ().variable (),
diff --git a/src/dbgengine/nmv-i-var-walker.h b/src/dbgengine/nmv-i-var-walker.h
index 825b292..ade767e 100644
--- a/src/dbgengine/nmv-i-var-walker.h
+++ b/src/dbgengine/nmv-i-var-walker.h
@@ -60,30 +60,30 @@ public:
/// emitted each time one of the members node of a variable is
/// visited.
virtual sigc::signal<void,
- const IDebugger::VariableSafePtr&>&
- visited_variable_node_signal () const = 0;
+ const IDebugger::VariableSafePtr>
+ visited_variable_node_signal () const = 0;
/// emitted when the root variable (the one the walker has been connected
/// has been totally visited. That means when all its members nodes have
/// been visited.
virtual sigc::signal<void,
- const IDebugger::VariableSafePtr&>&
+ const IDebugger::VariableSafePtr>
visited_variable_signal () const = 0;
///@}
/// connect the walker to a variable and to a debugger
/// that will be use to walk that variable
- virtual void connect (IDebuggerSafePtr &a_debugger,
+ virtual void connect (IDebuggerSafePtr a_debugger,
const UString &a_var_name) = 0;
- virtual void connect (IDebuggerSafePtr &a_debugger,
- const IDebugger::VariableSafePtr &a_var) = 0;
+ virtual void connect (IDebuggerSafePtr a_debugger,
+ const IDebugger::VariableSafePtr a_var) = 0;
- virtual void do_walk_variable (const UString &a_cookie="") = 0;
+ virtual void do_walk_variable (const UString &a_cookie = "") = 0;
/// gets the root variable this walker is connected to.
/// this will return a non null variable if and only if
/// the visited_root_variabls_signal() has been emited already.
- virtual const IDebugger::VariableSafePtr& get_variable () const = 0;
+ virtual const IDebugger::VariableSafePtr get_variable () const = 0;
/// gets the debugger the walker is connected to
virtual IDebuggerSafePtr get_debugger () const = 0;
diff --git a/src/dbgengine/nmv-var-walker.cc b/src/dbgengine/nmv-var-walker.cc
index 86512b0..ba61343 100644
--- a/src/dbgengine/nmv-var-walker.cc
+++ b/src/dbgengine/nmv-var-walker.cc
@@ -57,13 +57,14 @@ struct SafePtrCmp {
return (l.get () < r.get ());
}
};
+
class VarWalker : public IVarWalker , public sigc::trackable {
mutable sigc::signal<void,
- const IDebugger::VariableSafePtr&> m_visited_variable_node_signal;
+ const IDebugger::VariableSafePtr> m_visited_variable_node_signal;
mutable sigc::signal<void,
- const IDebugger::VariableSafePtr&>
+ const IDebugger::VariableSafePtr>
m_visited_variable_signal;
mutable GDBEngineSafePtr m_debugger;
@@ -74,13 +75,13 @@ class VarWalker : public IVarWalker , public sigc::trackable {
IDebugger::VariableSafePtr m_root_var;
void on_variable_value_signal (const UString &a_name,
- const IDebugger::VariableSafePtr &a_var,
+ const IDebugger::VariableSafePtr a_var,
const UString &a_cookie);
- void on_variable_value_set_signal (const IDebugger::VariableSafePtr &a_var,
+ void on_variable_value_set_signal (const IDebugger::VariableSafePtr a_var,
const UString &a_cookie);
- void on_variable_type_set_signal (const IDebugger::VariableSafePtr &a_var,
+ void on_variable_type_set_signal (const IDebugger::VariableSafePtr a_var,
const UString &a_cookie);
void get_type_of_all_members (const IDebugger::VariableSafePtr a_from);
@@ -95,28 +96,29 @@ public:
//********************
//<event getters>
//********************
- sigc::signal<void, const IDebugger::VariableSafePtr&>&
+ sigc::signal<void, const IDebugger::VariableSafePtr>
visited_variable_node_signal () const;
- sigc::signal<void, const IDebugger::VariableSafePtr&>&
+ sigc::signal<void, const IDebugger::VariableSafePtr>
visited_variable_signal () const;
//********************
//</event getters>
//********************
- void connect (IDebuggerSafePtr &a_debugger, const UString &a_var_name);
+ void connect (IDebuggerSafePtr a_debugger, const UString &a_var_name);
- void connect (IDebuggerSafePtr &a_debugger, const IDebugger::VariableSafePtr &a_var);
+ void connect (IDebuggerSafePtr a_debugger,
+ const IDebugger::VariableSafePtr a_var);
void do_walk_variable (const UString &a_cookie="");
- const IDebugger::VariableSafePtr& get_variable () const;
+ const IDebugger::VariableSafePtr get_variable () const;
IDebuggerSafePtr get_debugger () const ;
};//end class VarWalker
void
VarWalker::on_variable_value_signal (const UString &a_name,
- const IDebugger::VariableSafePtr &a_var,
+ const IDebugger::VariableSafePtr a_var,
const UString &a_cookie)
{
if (a_name.raw () == "") {}
@@ -135,7 +137,7 @@ VarWalker::on_variable_value_signal (const UString &a_name,
}
void
-VarWalker::on_variable_value_set_signal (const IDebugger::VariableSafePtr &a_var,
+VarWalker::on_variable_value_set_signal (const IDebugger::VariableSafePtr a_var,
const UString &a_cookie)
{
if (a_cookie.raw () != m_cookie.raw ()) {
@@ -153,7 +155,7 @@ VarWalker::on_variable_value_set_signal (const IDebugger::VariableSafePtr &a_var
}
void
-VarWalker::on_variable_type_set_signal (const IDebugger::VariableSafePtr &a_var,
+VarWalker::on_variable_type_set_signal (const IDebugger::VariableSafePtr a_var,
const UString &a_cookie)
{
if (a_cookie.raw () != m_cookie.raw ()) {
@@ -234,20 +236,20 @@ VarWalker::get_type_of_all_members (const IDebugger::VariableSafePtr a_from)
LOG_DD ("m_vars_to_visit.size () = " << (int)m_vars_to_visit.size ());
}
-sigc::signal<void, const IDebugger::VariableSafePtr&>&
+sigc::signal<void, const IDebugger::VariableSafePtr>
VarWalker::visited_variable_node_signal () const
{
return m_visited_variable_node_signal;
}
-sigc::signal<void, const IDebugger::VariableSafePtr&>&
+sigc::signal<void, const IDebugger::VariableSafePtr>
VarWalker::visited_variable_signal () const
{
return m_visited_variable_signal;
}
void
-VarWalker::connect (IDebuggerSafePtr &a_debugger,
+VarWalker::connect (IDebuggerSafePtr a_debugger,
const UString &a_var_name)
{
m_debugger = a_debugger.do_dynamic_cast<GDBEngine> ();
@@ -265,8 +267,8 @@ VarWalker::connect (IDebuggerSafePtr &a_debugger,
}
void
-VarWalker::connect (IDebuggerSafePtr &a_debugger,
- const IDebugger::VariableSafePtr &a_var)
+VarWalker::connect (IDebuggerSafePtr a_debugger,
+ const IDebugger::VariableSafePtr a_var)
{
m_debugger = a_debugger.do_dynamic_cast<GDBEngine> ();
THROW_IF_FAIL (m_debugger);
@@ -304,7 +306,7 @@ VarWalker::do_walk_variable (const UString &a_cookie)
}
}
-const IDebugger::VariableSafePtr&
+const IDebugger::VariableSafePtr
VarWalker::get_variable () const
{
return m_root_var;
diff --git a/src/dbgengine/nmv-varobj-walker.cc b/src/dbgengine/nmv-varobj-walker.cc
new file mode 100644
index 0000000..a60b1cd
--- /dev/null
+++ b/src/dbgengine/nmv-varobj-walker.cc
@@ -0,0 +1,303 @@
+//Author: Dodji Seketeli
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#include <list>
+#include <map>
+#include "nmv-i-var-walker.h"
+#include "nmv-gdb-engine.h"
+#include "common/nmv-sequence.h"
+
+using std::list;
+using std::map;
+using nemiver::common::DynamicModule;
+using nemiver::common::DynamicModuleSafePtr;
+using nemiver::common::DynModIface;
+using nemiver::common::DynModIfaceSafePtr;
+using nemiver::common::ObjectRef;
+using nemiver::common::ObjectUnref;
+
+typedef SafePtr<nemiver::GDBEngine, ObjectRef, ObjectUnref> GDBEngineSafePtr;
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
+const UString VAR_WALKER_COOKIE="var-walker-cookie";
+
+
+class VarobjWalker : public IVarWalker, public sigc::trackable
+{
+ mutable sigc::signal<void,
+ const IDebugger::VariableSafePtr>
+ m_visited_variable_node_signal;
+ mutable sigc::signal<void,
+ const IDebugger::VariableSafePtr>
+ m_visited_variable_signal;
+ IDebuggerSafePtr m_debugger;
+ IDebugger::VariableSafePtr m_variable;
+ UString m_var_name;
+ bool m_do_walk;
+ // The count of on going variable unfolding
+ int m_variable_unfolds;
+
+ VarobjWalker (); // Don't call this constructor.
+
+public:
+ VarobjWalker (DynamicModule *a_dynmod) :
+ IVarWalker (a_dynmod),
+ m_do_walk (false),
+ m_variable_unfolds (0)
+ {
+ }
+
+ ~VarobjWalker ()
+ {
+ if (m_variable && m_debugger)
+ m_debugger->delete_variable (m_variable);
+ }
+
+ sigc::signal<void,
+ const IDebugger::VariableSafePtr>
+ visited_variable_node_signal () const;
+ sigc::signal<void,
+ const IDebugger::VariableSafePtr>
+ visited_variable_signal () const;
+
+ void connect (IDebuggerSafePtr a_debugger,
+ const UString &a_var_name);
+
+ void connect (IDebuggerSafePtr a_debugger,
+ const IDebugger::VariableSafePtr a_var);
+
+ void do_walk_variable (const UString &a_cookie="");
+
+ const IDebugger::VariableSafePtr get_variable () const;
+
+ IDebuggerSafePtr get_debugger () const;
+
+ void do_walk_variable_real (const IDebugger::VariableSafePtr);
+
+ void on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_var);
+
+ void on_variable_created_signal (const IDebugger::VariableSafePtr a_var);
+}; // end class VarobjWalker.
+
+sigc::signal<void,
+ const IDebugger::VariableSafePtr>
+VarobjWalker::visited_variable_node_signal () const
+{
+ return m_visited_variable_node_signal;
+}
+
+sigc::signal<void,
+ const IDebugger::VariableSafePtr>
+VarobjWalker::visited_variable_signal () const
+{
+ return m_visited_variable_signal;
+}
+
+void
+VarobjWalker::connect (IDebuggerSafePtr a_debugger,
+ const UString &a_var_name)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ THROW_IF_FAIL (a_debugger);
+ THROW_IF_FAIL (!a_var_name.empty ());
+
+ m_debugger = a_debugger;
+ m_var_name = a_var_name;
+ m_debugger->create_variable
+ (a_var_name,
+ sigc::mem_fun (*this, &VarobjWalker::on_variable_created_signal));
+
+}
+
+void
+VarobjWalker::connect (IDebuggerSafePtr a_debugger,
+ const IDebugger::VariableSafePtr a_var)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ THROW_IF_FAIL (a_debugger);
+ THROW_IF_FAIL (a_var);
+ // The variable must be backed by variable objects.
+ THROW_IF_FAIL (!a_var->internal_name ().empty ());
+
+ m_debugger = a_debugger;
+ m_variable = a_var;
+}
+
+void
+VarobjWalker::do_walk_variable (const UString &)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ if (!m_variable) {
+ if (!m_var_name.empty ()) {
+ LOG_DD ("setting m_do_walk to true");
+ m_do_walk = true;
+ return;
+ } else {
+ THROW ("expecting a non null m_variable!");
+ }
+ }
+ do_walk_variable_real (m_variable);
+
+}
+
+const IDebugger::VariableSafePtr
+VarobjWalker::get_variable () const
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ return m_variable;
+}
+
+IDebuggerSafePtr
+VarobjWalker::get_debugger () const
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ return m_debugger;
+}
+
+void
+VarobjWalker::do_walk_variable_real (const IDebugger::VariableSafePtr a_var)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ THROW_IF_FAIL (a_var);
+
+ if (a_var->needs_unfolding ()) {
+ LOG_DD ("needs unfolding");
+ m_variable_unfolds++;
+ m_debugger->unfold_variable
+ (a_var, sigc::mem_fun (*this,
+ &VarobjWalker::on_variable_unfolded_signal));
+ } else if (!a_var->members ().empty ()) {
+ LOG_DD ("children need visiting");
+ visited_variable_node_signal ().emit (a_var);
+ IDebugger::VariableList::const_iterator it;
+ for (it = a_var->members ().begin ();
+ it != a_var->members ().end ();
+ ++ it) {
+ do_walk_variable_real (*it);
+ }
+ } else {
+ LOG_DD ("else finished ?. m_variable_unfolds: "
+ << (int) m_variable_unfolds);
+ visited_variable_node_signal ().emit (a_var);
+ if (m_variable_unfolds == 0)
+ visited_variable_signal ().emit (a_var);
+ }
+
+}
+
+void
+VarobjWalker::on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_var)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ NEMIVER_TRY
+
+ m_variable_unfolds--;
+ visited_variable_node_signal ().emit (a_var);
+ do_walk_variable_real (a_var);
+ if (m_variable_unfolds == 0) {
+ THROW_IF_FAIL (m_variable);
+ visited_variable_signal ().emit (m_variable);
+ }
+
+ NEMIVER_CATCH_NOX
+}
+
+void
+VarobjWalker::on_variable_created_signal (const IDebugger::VariableSafePtr a_var)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ NEMIVER_TRY
+
+ THROW_IF_FAIL (a_var);
+
+ m_variable = a_var;
+
+ if (m_do_walk) {
+ do_walk_variable ();
+ m_do_walk = false;
+ } else {
+ LOG_DD ("m_do_walk is false");
+ }
+
+ NEMIVER_CATCH_NOX
+}
+
+// the dynmod used to instanciate the VarWalker service object
+// and return an interface on it.
+struct VarobjWalkerDynMod : public DynamicModule
+{
+
+ void
+ get_info (Info &a_info) const
+ {
+ const static Info s_info ("VarobjWalker",
+ "The Variable Object Walker dynmod. "
+ "Implements the IVarWalker interface",
+ "1.0");
+ a_info = s_info;
+ }
+
+ void
+ do_init ()
+ {
+ }
+
+ bool
+ lookup_interface (const std::string &a_iface_name,
+ DynModIfaceSafePtr &a_iface)
+ {
+ if (a_iface_name == "IVarWalker") {
+ a_iface.reset (new VarobjWalker (this));
+ } else {
+ return false;
+ }
+ return true;
+ }
+}; //end class VarobjListDynMod
+
+//the dynmod initial factory.
+extern "C"
+{
+
+bool
+NEMIVER_API nemiver_common_create_dynamic_module_instance (void **a_new_instance)
+{
+ *a_new_instance = new nemiver::VarobjWalkerDynMod ();
+ return (*a_new_instance != 0);
+}
+
+}
+
+NEMIVER_END_NAMESPACE(nemiver)
+
+
diff --git a/src/dbgengine/varobjwalker.conf.in b/src/dbgengine/varobjwalker.conf.in
new file mode 100644
index 0000000..cd39d37
--- /dev/null
+++ b/src/dbgengine/varobjwalker.conf.in
@@ -0,0 +1,10 @@
+<moduleconfig>
+ <module>
+ <name>varobjwalker</name>
+ <libraryname>varobjwalkermod</libraryname>
+ </module>
+ <customsearchpaths>
+ <path>@NEMIVER_LIBDIR@/nemiver/modules</path>
+ </customsearchpaths>
+</moduleconfig>
+
diff --git a/src/persp/dbgperspective/menus/varinspectorpopup.xml b/src/persp/dbgperspective/menus/varinspectorpopup.xml
index dd42b04..7343c93 100644
--- a/src/persp/dbgperspective/menus/varinspectorpopup.xml
+++ b/src/persp/dbgperspective/menus/varinspectorpopup.xml
@@ -3,6 +3,8 @@
<popup name="VarInspectorPopup">
<menuitem action="CopyVariablePathMenuItemAction"
name="CopyVariablePathMenuItem" />
+ <menuitem action="CopyVariableValueMenuItemAction"
+ name="CopyVariableValueMenuItem" />
</popup>
</ui>
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 19058b8..ebeb902 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,7 @@
if VAROBJS
WATCHPOINT_TEST=runtestwatchpoint
VAR_PATH_EXPR_TEST=runtestvarpathexpr
+ VAROBJ_WALKER_TEST=runtestvarobjwalker
else
WATCHPOINT_TEST=
endif
@@ -14,14 +15,13 @@ if AUTOTESTS
TESTS=\
runtestgdbmi runtestunicode \
runtestvars runtestcpptrait runtestvarlist \
-runtestvarwalker runtestbreakpoint \
+runtestvarwalker $(VAROBJ_WALKER_TEST) runtestbreakpoint \
$(WATCHPOINT_TEST) runtestderef \
runtestlocalvarslist runtestcpplexer \
runtestcppparser $(VAR_PATH_EXPR_TEST) \
runtestlibtoolwrapperdetection \
runtestenv runtesttypes
-
else
TESTS=
@@ -63,6 +63,11 @@ $(top_builddir)/src/common/libnemivercommon.la
runtestvarpathexpr_SOURCES=test-var-path-expr.cc
runtestvarpathexpr_LDADD= NEMIVERCOMMON_LIBS@ \
$(top_builddir)/src/common/libnemivercommon.la
+
+runtestvarobjwalker_SOURCES=test-varobj-walker.cc
+runtestvarobjwalker_LDADD= NEMIVERCOMMON_LIBS@ @BOOST_TEST_EXEC_MONITOR_LIB@ \
+$(top_builddir)/src/common/libnemivercommon.la
+
endif
#runtestoverloads_SOURCES=test-overloads.cc
@@ -82,7 +87,6 @@ runtestcpptrait_LDADD= NEMIVERCOMMON_LIBS@ \
@BOOST_UNIT_TEST_FRAMEWORK_STATIC_LIB@ \
$(top_builddir)/src/common/libnemivercommon.la
-
runtestunicode_SOURCES=test-unicode.cc
runtestunicode_LDADD= NEMIVERCOMMON_LIBS@ \
@BOOST_UNIT_TEST_FRAMEWORK_STATIC_LIB@ \
diff --git a/tests/test-varobj-walker.cc b/tests/test-varobj-walker.cc
new file mode 100644
index 0000000..8050415
--- /dev/null
+++ b/tests/test-varobj-walker.cc
@@ -0,0 +1,190 @@
+#include <iostream>
+#include <sstream>
+#include <map>
+#include <string>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/minimal.hpp>
+#include <glibmm.h>
+#include "common/nmv-initializer.h"
+#include "common/nmv-exception.h"
+#include "nmv-i-var-list-walker.h"
+
+using namespace nemiver;
+using namespace nemiver::common;
+
+Glib::RefPtr<Glib::MainLoop> s_loop =
+ Glib::MainLoop::create (Glib::MainContext::get_default ());
+
+static std::string serialized_variable;
+
+static IVarWalkerSafePtr
+create_varobj_walker ()
+{
+ IVarWalkerSafePtr result =
+ DynamicModuleManager::load_iface_with_default_manager<IVarWalker>
+ ("varobjwalker", "IVarWalker");
+ return result;
+}
+
+static IVarWalkerSafePtr
+get_varobj_walker ()
+{
+ static IVarWalkerSafePtr var;
+ if (!var)
+ var = create_varobj_walker ();
+ return var;
+}
+
+static void
+gen_white_spaces (int a_nb_ws,
+ std::string &a_ws_str)
+{
+ for (int i = 0; i < a_nb_ws; i++) {
+ a_ws_str += ' ';
+ }
+
+}
+
+
+static void
+dump_variable_value (IDebugger::VariableSafePtr a_var,
+ int a_indent_num,
+ std::ostringstream &a_os)
+{
+ THROW_IF_FAIL (a_var);
+
+ std::string ws_string;
+ gen_white_spaces (a_indent_num, ws_string);
+
+ a_os << ws_string << a_var->name ();
+
+ if (!a_var->members ().empty ()) {
+ a_os << "\n" << ws_string << "{\n";
+ IDebugger::VariableList::const_iterator it;
+ for (it = a_var->members ().begin ();
+ it != a_var->members ().end ();
+ ++it) {
+ dump_variable_value (*it, a_indent_num + 2, a_os);
+ }
+ a_os << "\n" << ws_string << "}";
+ } else {
+ a_os << " = " << a_var->value ();
+ }
+}
+
+static void
+dump_variable_value (IDebugger::VariableSafePtr a_var,
+ int a_indent_num,
+ std::string &a_out_str)
+{
+ std::ostringstream os;
+ dump_variable_value (a_var, a_indent_num, os);
+ a_out_str = os.str ();
+}
+
+static void
+on_engine_died_signal ()
+{
+ s_loop->quit ();
+}
+
+static void
+on_program_finished_signal ()
+{
+ s_loop->quit ();
+}
+
+static void
+on_variable_visited_signal (const IDebugger::VariableSafePtr a_var)
+{
+ MESSAGE ("dumping the variable ...");
+ dump_variable_value (a_var, 0, serialized_variable);
+ MESSAGE ("dumping the variable: DONE");
+ s_loop->quit ();
+}
+
+
+static void
+do_varobj_walker_stuff (IDebuggerSafePtr a_debugger)
+{
+ MESSAGE ("do varobj walker stuff");
+
+ IVarWalkerSafePtr var_walker = get_varobj_walker ();
+
+ var_walker->visited_variable_signal ().connect (&on_variable_visited_signal);
+ var_walker->connect (a_debugger, "person");
+ var_walker->do_walk_variable ();
+}
+
+static void
+on_stopped_signal (IDebugger::StopReason a_reason,
+ bool /*a_has_frame*/,
+ const IDebugger::Frame &a_frame,
+ int /*a_thread_id*/,
+ int /*bp num*/,
+ const UString &/*a_cookie*/,
+ IDebuggerSafePtr &a_debugger)
+{
+ NEMIVER_TRY
+
+ BOOST_REQUIRE (a_debugger);
+
+ if (a_reason == IDebugger::BREAKPOINT_HIT) {
+ MESSAGE ("broke in main");
+ // We did break in main. We need to step once to pass the
+ // initialization of the person variable.
+ a_debugger->step_over ();
+ return;
+ } else if (a_frame.function_name () == "main") {
+ MESSAGE ("okay, stopped in main right after stepping");
+ do_varobj_walker_stuff (a_debugger);
+ }
+
+ NEMIVER_CATCH_NOX
+
+}
+
+NEMIVER_API int
+test_main (int, char **)
+{
+ NEMIVER_TRY
+
+ Initializer::do_init ();
+
+ //load the IDebugger interface
+ IDebuggerSafePtr debugger =
+ DynamicModuleManager::load_iface_with_default_manager<IDebugger>
+ ("gdbengine",
+ "IDebugger");
+ //setup the debugger with the glib mainloop
+ debugger->set_event_loop_context (Glib::MainContext::get_default ());
+
+ //*******************************
+ //<connect to IDebugger events>
+ //******************************
+ debugger->engine_died_signal ().connect (&on_engine_died_signal);
+ debugger->program_finished_signal ().connect (&on_program_finished_signal);
+ debugger->stopped_signal ().connect (sigc::bind (&on_stopped_signal,
+ debugger));
+ //*******************************
+ //</connect to IDebugger events>
+ //******************************
+
+ debugger->load_program ("fooprog", ".");
+ debugger->set_breakpoint ("main");
+
+ debugger->run ();
+
+ //****************************************
+ //run the event loop.
+ //****************************************
+ s_loop->run ();
+
+ NEMIVER_CATCH_AND_RETURN_NOX (-1)
+
+ BOOST_REQUIRE (!serialized_variable.empty ());
+ MESSAGE (serialized_variable);
+
+ return 0;
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]