Re-import test files from upstream, with proper copyright information
this time.

diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/apps/accessible-app.c pyatspi2/tests/apps/accessible-app.c
--- pyatspi2.old/tests/apps/accessible-app.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/apps/accessible-app.c	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gmodule.h>
+#include <atk/atk.h>
+#include <my-atk.h>
+
+#include "atk-object-xml-loader.h"
+
+static gchar *tdata_path = NULL;
+
+static AtkObject *root_accessible;
+
+static AtkStateType states[] =
+{
+  ATK_STATE_MULTI_LINE,
+  ATK_STATE_MODAL,
+  ATK_STATE_INDETERMINATE,
+  ATK_STATE_SUPPORTS_AUTOCOMPLETION,
+  ATK_STATE_VERTICAL
+};
+
+#define OBJECT_TEST_1 "accessible-test.xml"
+
+G_MODULE_EXPORT void
+test_init (gchar *path)
+{
+  AtkStateSet *ss;
+  gchar *td;
+
+  if (path == NULL)
+     g_error("No test data path provided");
+  tdata_path = path;
+
+  td = g_build_path(G_DIR_SEPARATOR_S, tdata_path, OBJECT_TEST_1, NULL);
+  root_accessible = ATK_OBJECT(atk_object_xml_parse(td));
+  g_free(td);
+
+  ss = atk_object_ref_state_set(ATK_OBJECT(root_accessible));
+  atk_state_set_add_states(ss, states, 5);
+  g_object_unref(G_OBJECT(ss));
+}
+
+G_MODULE_EXPORT void
+test_next (int argc, char *argv[])
+{
+  ;
+}
+
+G_MODULE_EXPORT void
+test_finished (int argc, char *argv[])
+{
+  ;
+}
+
+G_MODULE_EXPORT AtkObject *
+test_get_root (void)
+{
+  return root_accessible;
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/apps/action-app.c pyatspi2/tests/apps/action-app.c
--- pyatspi2.old/tests/apps/action-app.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/apps/action-app.c	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gmodule.h>
+#include <atk/atk.h>
+#include <my-atk.h>
+
+static AtkObject *root_accessible;
+
+G_MODULE_EXPORT void
+test_init (gchar *path)
+{
+  root_accessible  = g_object_new(MY_TYPE_ATK_ACTION, NULL);
+  root_accessible->name = g_strdup ("atspi-test-main");
+  root_accessible->role = ATK_ROLE_APPLICATION;
+}
+
+G_MODULE_EXPORT void
+test_next (int argc, char *argv[])
+{
+  g_print("Moving to next stage\n");
+}
+
+G_MODULE_EXPORT void
+test_finished (int argc, char *argv[])
+{
+  g_print("Test has completed\n");
+}
+
+G_MODULE_EXPORT AtkObject *
+test_get_root (void)
+{
+  return root_accessible;
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/apps/atk-object-xml-loader.c pyatspi2/tests/apps/atk-object-xml-loader.c
--- pyatspi2.old/tests/apps/atk-object-xml-loader.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/apps/atk-object-xml-loader.c	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include <my-atk.h>
+
+#define ACCESSIBLE_NODE ((const xmlChar *) "accessible")
+#define INTERFACE_NODE  ((const xmlChar *) "interface")
+
+#define NAME_ATTR ((const xmlChar *) "name")
+#define DESC_ATTR ((const xmlChar *) "description")
+#define ROLE_ATTR ((const xmlChar *) "role")
+#define TYPE_ATTR ((const xmlChar *) "type")
+
+static MyAtkObject *
+create_atk_object_from_element(xmlNode *element)
+{
+  xmlNode *child_node;
+
+  MyAtkObject *obj = NULL;
+  MyAtkObject *child_obj;
+
+  xmlChar *name;
+  xmlChar *description;
+  xmlChar *role_text; 
+  xmlChar *type_text;
+  gint role;
+  GType type = MY_TYPE_ATK_OBJECT;
+
+  name = xmlGetProp(element, NAME_ATTR);
+  description = xmlGetProp(element, DESC_ATTR);
+  role_text = xmlGetProp(element, ROLE_ATTR);
+  role = atoi(role_text);
+  type_text = xmlGetProp(element, TYPE_ATTR);
+
+  if (type_text && !strcmp (type_text, "document"))
+    type = MY_TYPE_ATK_DOCUMENT;
+
+  obj = MY_ATK_OBJECT(g_object_new(type,
+				   "accessible-name", name,
+				   "accessible-description", description,
+				   "accessible-role", role,
+				   NULL));
+
+  child_node = element->xmlChildrenNode;
+  while (child_node != NULL)
+    {
+      if (!xmlStrcmp(child_node->name, ACCESSIBLE_NODE))  
+	{
+	  child_obj = create_atk_object_from_element(child_node); 
+	  my_atk_object_add_child(obj, child_obj);
+	}
+      child_node = child_node->next;
+    }
+  return obj;
+}
+
+/*
+ * Reads the XML from filename and uses it
+ * to create a tree of MyAtkObjects.
+ * 
+ * returns: The root object of the tree.
+ */
+MyAtkObject *
+atk_object_xml_parse(gchar *filename)
+{
+  xmlDoc *doc;
+  xmlNode *root_element;
+  MyAtkObject *new_atk_object = NULL;
+
+  doc = xmlReadFile(filename, NULL, 0);
+  g_assert(doc != NULL);
+
+  root_element = xmlDocGetRootElement(doc);
+
+  if (!xmlStrcmp(root_element->name, ACCESSIBLE_NODE))  
+    new_atk_object = create_atk_object_from_element(root_element); 
+
+  xmlFreeDoc(doc);
+  return new_atk_object;
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/apps/atk-object-xml-loader.h pyatspi2/tests/apps/atk-object-xml-loader.h
--- pyatspi2.old/tests/apps/atk-object-xml-loader.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/apps/atk-object-xml-loader.h	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ATK_OBJECT_XML_LOADER_H
+#define ATK_OBJECT_XML_LOADER_H
+
+#include <glib.h>
+#include <my-atk.h>
+
+MyAtkObject *
+atk_object_xml_parse(gchar *filename);
+
+#endif /*ATK_OBJECT_XML_LOADER_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/apps/component-app.c pyatspi2/tests/apps/component-app.c
--- pyatspi2.old/tests/apps/component-app.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/apps/component-app.c	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gmodule.h>
+#include <atk/atk.h>
+#include <my-atk.h>
+
+static gchar *tdata_path = NULL;
+
+static AtkComponent *comps[] = {NULL, NULL, NULL};
+static const AtkRectangle extents[] = {{0,0,30,20}, {40,30,30,40}, {0,0,70,70}};
+static const AtkLayer layers[] = {ATK_LAYER_WINDOW, ATK_LAYER_WIDGET, ATK_LAYER_MDI};
+static const guint zorders[] = {0, -100, 100};
+static const gboolean extent_may_changed[] = {TRUE, FALSE, TRUE};
+
+G_MODULE_EXPORT void
+test_init (gchar *path)
+{
+  int i;
+  AtkObject *atk;
+
+  if (path == NULL)
+     g_error("No test data path provided");
+  tdata_path = path;
+
+  g_type_init();
+  for(i = 0; i < sizeof(comps) / sizeof(comps[0]); i++)
+    {
+      MyAtkComponent *mycomp = MY_ATK_COMPONENT(g_object_new(MY_TYPE_ATK_COMPONENT, NULL));
+        
+      mycomp->extent = extents[i];
+      mycomp->is_extent_may_changed = extent_may_changed[i];
+      mycomp->layer = layers[i];
+      mycomp->zorder = zorders[i];
+      
+      comps[i] = ATK_COMPONENT(mycomp);
+    }
+    
+  my_atk_object_add_child(MY_ATK_OBJECT(comps[2]), MY_ATK_OBJECT(comps[0]));
+  my_atk_object_add_child(MY_ATK_OBJECT(comps[2]), MY_ATK_OBJECT(comps[1]));
+
+    atk = ATK_OBJECT (comps [2]);
+    atk->name = g_strdup ("atspi-test-main");
+    atk->role = ATK_ROLE_APPLICATION;
+}
+
+G_MODULE_EXPORT void
+test_next (int argc, char *argv[])
+{
+  g_print("Moving to next stage\n");
+}
+
+G_MODULE_EXPORT void
+test_finished (int argc, char *argv[])
+{
+  g_print("Test has completed\n");
+}
+
+G_MODULE_EXPORT AtkObject *
+test_get_root (void)
+{
+  return ATK_OBJECT(comps[2]);
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/apps/Makefile.am pyatspi2/tests/apps/Makefile.am
--- pyatspi2.old/tests/apps/Makefile.am	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/apps/Makefile.am	2019-08-26 23:04:09.541759565 +0200
@@ -0,0 +1,47 @@
+check_PROGRAMS = test-application
+check_LTLIBRARIES = libnoopapp.la \
+		    libaccessibleapp.la \
+		    libcomponentapp.la \
+		    libactionapp.la \
+		    librelationapp.la
+
+test_application_CFLAGS = $(DBUS_GLIB_CFLAGS)	\
+			  $(ATK_CFLAGS)		\
+			  $(GMODULE_CFLAGS)	\
+		       	  -I$(top_srcdir)
+
+test_application_LDADD = $(DBUS_GLIB_LIBS)	\
+		         $(GMODULE_LIBS)	\
+		         $(ATK_LIBS)
+
+test_application_SOURCES = test-application.c
+
+
+TEST_APP_CFLAGS = $(ATK_CFLAGS) $(GMODULE_CFLAGS) -I$(top_srcdir) -I$(top_srcdir)/tests/dummyatk/
+TEST_APP_LDFLAGS = -no-undefined -module -avoid-version -rpath /a/fake/path
+TEST_APP_LIBADD = $(ATK_LIBS) $(GMODULE_LIBS) $(top_builddir)/tests/dummyatk/libdummyatk.la
+
+libnoopapp_la_CFLAGS = $(TEST_APP_CFLAGS)
+libnoopapp_la_LDFLAGS = $(TEST_APP_LDFLAGS)
+libnoopapp_la_LIBADD = $(TEST_APP_LIBADD)
+libnoopapp_la_SOURCES = noop-app.c
+
+libaccessibleapp_la_CFLAGS = $(TEST_APP_CFLAGS) $(LIB_XML_CFLAGS)
+libaccessibleapp_la_LDFLAGS = $(TEST_APP_LDFLAGS)
+libaccessibleapp_la_LIBADD = $(TEST_APP_LIBADD) $(LIB_XML_LIBS)
+libaccessibleapp_la_SOURCES = accessible-app.c atk-object-xml-loader.c atk-object-xml-loader.h
+
+libcomponentapp_la_CFLAGS = $(TEST_APP_CFLAGS)
+libcomponentapp_la_LDFLAGS = $(TEST_APP_LDFLAGS)
+libcomponentapp_la_LIBADD = $(TEST_APP_LIBADD)
+libcomponentapp_la_SOURCES = component-app.c
+
+libactionapp_la_CFLAGS = $(TEST_APP_CFLAGS)
+libactionapp_la_LDFLAGS = $(TEST_APP_LDFLAGS)
+libactionapp_la_LIBADD = $(TEST_APP_LIBADD)
+libactionapp_la_SOURCES = action-app.c
+
+librelationapp_la_CFLAGS = $(TEST_APP_CFLAGS)
+librelationapp_la_LDFLAGS = $(TEST_APP_LDFLAGS)
+librelationapp_la_LIBADD = $(TEST_APP_LIBADD)
+librelationapp_la_SOURCES = relation-app.c
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/apps/noop-app.c pyatspi2/tests/apps/noop-app.c
--- pyatspi2.old/tests/apps/noop-app.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/apps/noop-app.c	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gmodule.h>
+#include <atk/atk.h>
+
+G_MODULE_EXPORT void
+test_init (int argc, char *argv[])
+{
+  ;
+}
+
+G_MODULE_EXPORT void
+test_next (int argc, char *argv[])
+{
+  ;
+}
+
+G_MODULE_EXPORT void
+test_finished (int argc, char *argv[])
+{
+  ;
+}
+
+G_MODULE_EXPORT AtkObject *
+test_get_root (void)
+{
+  return NULL;
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/apps/relation-app.c pyatspi2/tests/apps/relation-app.c
--- pyatspi2.old/tests/apps/relation-app.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/apps/relation-app.c	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gmodule.h>
+#include <atk/atk.h>
+#include <my-atk.h>
+
+static AtkObject *root_accessible;
+
+G_MODULE_EXPORT void
+test_init (gchar *path)
+{
+  AtkObject *r1, *r2, *r3;
+  AtkObject *m1, *m2, *m3;
+  AtkRelationSet *rset;
+  AtkRelation *rel;
+  AtkObject *rls[3];
+
+  root_accessible  = g_object_new(MY_TYPE_ATK_OBJECT, NULL);
+  root_accessible->name = g_strdup ("atspi-test-main");
+  root_accessible->role = ATK_ROLE_APPLICATION;
+  
+  r1 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+				  "accessible-name", "r1",
+				  "accessible-description", "",
+				  "accessible-role", ATK_ROLE_INVALID,
+				  NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(r1));
+
+  r2 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+				  "accessible-name", "r2",
+				  "accessible-description", "",
+				  "accessible-role", ATK_ROLE_INVALID,
+				  NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(r2));
+
+  r3 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+				  "accessible-name", "r3",
+				  "accessible-description", "",
+				  "accessible-role", ATK_ROLE_INVALID,
+				  NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(r3));
+
+  m1 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+				  "accessible-name", "m1",
+				  "accessible-description", "",
+				  "accessible-role", ATK_ROLE_INVALID,
+				  NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(m1));
+
+  m2 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+				  "accessible-name", "m2",
+				  "accessible-description", "",
+				  "accessible-role", ATK_ROLE_INVALID,
+				  NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(m2));
+
+  m3 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+				  "accessible-name", "m3",
+				  "accessible-description", "",
+				  "accessible-role", ATK_ROLE_INVALID,
+				  NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(m3));
+
+  atk_object_add_relationship(root_accessible, ATK_RELATION_EMBEDS, r1);
+  atk_object_add_relationship(root_accessible, ATK_RELATION_PARENT_WINDOW_OF, r2);
+  atk_object_add_relationship(root_accessible, ATK_RELATION_DESCRIBED_BY, r3);
+
+  rls[0] = m1;
+  rls[1] = m2;
+  rls[2] = m3;
+
+  rset = atk_object_ref_relation_set(root_accessible);
+  rel = atk_relation_new(rls, 3, ATK_RELATION_POPUP_FOR);
+  atk_relation_set_add(rset, rel);
+  g_object_unref(G_OBJECT(rset));
+}
+
+G_MODULE_EXPORT void
+test_next (int argc, char *argv[])
+{
+  g_print("Moving to next stage\n");
+}
+
+G_MODULE_EXPORT void
+test_finished (int argc, char *argv[])
+{
+  g_print("Test has completed\n");
+}
+
+G_MODULE_EXPORT AtkObject *
+test_get_root (void)
+{
+  return root_accessible;
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/apps/test-application.c pyatspi2/tests/apps/test-application.c
--- pyatspi2.old/tests/apps/test-application.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/apps/test-application.c	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,291 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Testing AT-SPI requires both a test application and AT client. 
+ * Test applications are built using the Dummy ATK implementation: MyAtk.
+ * This file contains the entry point for all test applications.
+ * Each test is built as a GModule, and this program loads the 
+ * test module, as well as the AT-SPI module. The test module will
+ * provide its own implementation of atk_get_root, and as such provide
+ * all the application state for the test.
+ */
+
+#include <stdlib.h>
+#include <glib.h>
+#include <gmodule.h>
+#include <atk/atk.h>
+#include <dbus/dbus.h>
+
+/* The test module, GModule containing interface for an atk-test */
+static GModule *test_module;
+static gpointer test_module_get_root;
+static gpointer test_module_next;
+static gpointer test_module_finished;
+
+static DBusConnection *dbus_bus;
+static GMainLoop *mainloop;
+
+/* Test module interface */
+/*************************/
+
+typedef AtkObject *(*TestModuleGetRoot) (void);
+
+/* Calls into the test module to get the root atk object */
+static AtkObject *
+get_root(void)
+{
+  return ((TestModuleGetRoot) test_module_get_root)();
+}
+
+typedef void (*VoidVoid) (void);
+
+/* Called to move to next stage of test.*/
+static void
+next(void)
+{
+  ((VoidVoid) test_module_next)();
+}
+
+
+/*************************/
+
+/* The AtkUtil class is called to find the root accessible and to deal
+ * with events. Its an incomplete class, its v-table needs to be filled in.
+ */
+static void
+setup_atk_util(void)
+{
+  AtkUtilClass *klass;
+
+  klass = g_type_class_ref(ATK_TYPE_UTIL);
+  klass->get_root = get_root;
+  g_type_class_unref(klass);
+}
+
+typedef void (*GtkModuleInit) (int *argc, char **argv[]);
+
+/* AT-SPI is a gtk module that must be loaded and initialized */
+static void
+load_atspi_module(const char *path, int *argc, char **argv[])
+{
+  GModule *bridge;
+  gpointer init;
+
+  bridge = g_module_open(path, G_MODULE_BIND_LOCAL|G_MODULE_BIND_LAZY);
+  if (!bridge)
+    g_error("Couldn't load atk-bridge module : %s\n", g_module_error());
+
+  if (!g_module_symbol(bridge, "gtk_module_init", &init))
+    g_error("Couldn't load symbol \"gtk_module_init\"\n");
+
+  ((GtkModuleInit) init)(argc, argv);
+}
+
+typedef void (*TestModuleInit) (gchar *path);
+
+static void
+load_test_module(const char *path, const char *tdpath)
+{
+  gpointer init;
+
+  test_module = g_module_open(path, G_MODULE_BIND_LOCAL|G_MODULE_BIND_LAZY);
+  if (!test_module)
+    g_error("Couldn't load test module : %s\n", path);
+
+  if (!g_module_symbol(test_module, "test_init", &init))
+    g_error("Couldn't load symbol \"test_init\"\n");
+
+  if (!g_module_symbol(test_module, "test_get_root", &test_module_get_root))
+    g_error("Couldn't load symbol \"test_get_root\"\n");
+
+  if (!g_module_symbol(test_module, "test_next", &test_module_next))
+    g_error("Couldn't load symbol \"test_next\"\n");
+
+  if (!g_module_symbol(test_module, "test_finished", &test_module_finished))
+    g_error("Couldn't load symbol \"test_finished\"\n");
+
+  ((TestModuleInit) init)((gchar *)tdpath);
+}
+
+static const char* introspection_string = 
+"<node name=\"/org/codethink/atspi/test\">"
+"	<interface name=\"org.codethink.atspi.test\">"
+"		<method name=\"next\"/>"
+"		<method name=\"finish\"/>"
+"               <signal name=\"started\"/>"
+"	</interface>"
+"</node>";
+
+static DBusHandlerResult
+message_handler (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+  const char *iface = dbus_message_get_interface (message);
+  const char *member = dbus_message_get_member (message);
+  DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  gboolean exit = FALSE;
+
+  DBusMessage *reply = NULL;
+
+  g_return_val_if_fail(iface != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+  
+  if (!strcmp(iface, "org.codethink.atspi.test"))
+    {
+      if (!strcmp(member, "next"))
+	{
+	  next();
+          reply = dbus_message_new_method_return (message);
+	  g_assert(reply != NULL);
+	  result = DBUS_HANDLER_RESULT_HANDLED;
+	}
+
+      if (!strcmp(member, "finish"))
+	{
+	  ((VoidVoid) test_module_finished)();
+          reply = dbus_message_new_method_return (message);
+	  g_assert(reply != NULL);
+	  result = DBUS_HANDLER_RESULT_HANDLED;
+	  exit = TRUE;
+	}
+    }
+
+  if (!strcmp(iface, "org.freedesktop.DBus.Introspectable"))
+    {
+      if (!strcmp(member, "Introspect"))
+	{
+	  reply = dbus_message_new_method_return (message);
+	  g_assert(reply != NULL);
+	  dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_string,
+				   DBUS_TYPE_INVALID);
+	  result = DBUS_HANDLER_RESULT_HANDLED;
+	}
+    }
+
+  if (reply)
+    {
+      dbus_connection_send (bus, reply, NULL);
+      dbus_message_unref (reply);
+    }
+
+  if (exit == TRUE)
+    {
+      dbus_connection_flush(bus);
+      dbus_connection_unref(bus);
+      g_main_loop_quit(mainloop);
+    }
+  return result;
+}
+
+static DBusObjectPathVTable test_vtable =
+{
+  NULL,
+  &message_handler,
+  NULL, NULL, NULL, NULL
+};
+
+static void
+init_dbus_interface(gchar *bus_name)
+{
+  DBusError error;
+
+  dbus_error_init(&error);
+  dbus_bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
+  g_print("\nUnique D-Bus name is: %s\n", dbus_bus_get_unique_name(dbus_bus));
+
+  if (!dbus_bus)
+    g_error("Couldn't get the session bus - %s\n", error.message);
+
+  if (bus_name)
+    dbus_bus_request_name (dbus_bus, bus_name, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
+
+  g_assert(dbus_connection_register_object_path(dbus_bus,
+						"/org/codethink/atspi/test",
+					       	&test_vtable,
+						NULL));
+
+  dbus_connection_setup_with_g_main(dbus_bus, g_main_context_default());
+}
+
+static void
+send_started_signal(void)
+{
+  DBusMessage* sig;
+  DBusMessageIter args;
+
+  sig = dbus_message_new_signal("/org/codethink/atspi/test", "org.codethink.atspi.test", "started");
+  g_assert(sig != NULL);
+  if (!dbus_connection_send(dbus_bus, sig, NULL))
+    g_error("Out of memory");
+  dbus_connection_flush(dbus_bus);
+  dbus_message_unref(sig);
+}
+
+/*Command line data*/
+static gchar *tmodule_path = NULL;
+static gchar *amodule_path = NULL;
+static gchar *tdata_path = NULL;
+static gchar *bus_name = NULL;
+
+static GOptionEntry optentries[] = 
+{
+  {"test-module", 0, 0, G_OPTION_ARG_STRING, &tmodule_path, "Module containing test scenario", NULL},
+  {"test-atspi-library", 0, 0, G_OPTION_ARG_STRING, &amodule_path, "Gtk module with atk-atspi adaptor", NULL},
+  {"test-data-directory", 0, 0, G_OPTION_ARG_STRING, &tdata_path, "Path to directory of test data", NULL},
+  {"test-dbus-name", 0, 0, G_OPTION_ARG_STRING, &bus_name, "Bus name", NULL},
+  {NULL}
+};
+
+/* main
+ * 
+ * Entry point for all test applications.
+ */
+main(int argc, char *argv[])
+{
+  GOptionContext *opt;
+  GError *err = NULL;
+
+  /*Parse command options*/
+  opt = g_option_context_new(NULL);
+  g_option_context_add_main_entries(opt, optentries, NULL);
+  g_option_context_set_ignore_unknown_options(opt, TRUE);
+  
+  if (!g_option_context_parse(opt, &argc, &argv, &err))
+      g_error("Option parsing failed: %s\n", err->message);
+
+  if (tmodule_path == NULL)
+      g_error("No test module provided");
+  if (amodule_path == NULL)
+      g_error("No atspi module provided");
+
+  g_type_init();
+
+  setup_atk_util();
+  load_test_module(tmodule_path, tdata_path);
+  load_atspi_module(amodule_path, &argc, &argv);
+  init_dbus_interface(bus_name);
+  send_started_signal();
+
+  mainloop = g_main_loop_new (NULL, FALSE);
+  g_main_loop_run (mainloop);
+
+  return 0;
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/data/accessible-test-results.xml pyatspi2/tests/data/accessible-test-results.xml
--- pyatspi2.old/tests/data/accessible-test-results.xml	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/data/accessible-test-results.xml	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,157 @@
+<!--
+
+Copyright 2008 Codethink Ltd.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+
+-->
+
+<?xml version="1.0" ?>
+<accessible description="The main accessible object, root of the accessible tree" name="atspi-test-main" role="69">
+	<accessible description="" name="gnome-settings-daemon" role="79"/>
+	<accessible description="" name="gnome-panel" role="79">
+		<accessible description="" name="Bottom Expanded Edge Panel" role="25"/>
+		<accessible description="" name="Top Expanded Edge Panel" role="25"/>
+	</accessible>
+	<accessible description="" name="nautilus" role="79">
+		<accessible description="" name="Desktop" role="25"/>
+	</accessible>
+	<accessible description="" name="metacity" role="79"/>
+	<accessible description="" name="tracker-applet" role="79"/>
+	<accessible description="" name="empathy" role="79">
+		<accessible description="" name="Contact List" role="25"/>
+	</accessible>
+	<accessible description="" name="nm-applet" role="79"/>
+	<accessible description="" name="gnome-power-manager" role="79"/>
+	<accessible description="" name="update-notifier" role="79"/>
+	<accessible description="Firefox Application Accessible" name="Firefox" role="79">
+		<accessible description="Firefox Application Accessible" name="Google Reader - Mozilla Firefox 3 Beta 5" role="25">
+			<accessible description="" name="" role="35"/>
+			<accessible description="" name="Strip originally conceived in conversation with Jeph Jacques. Soon to be a major motion picture." role="66"/>
+			<accessible description="" name="" role="68">
+				<accessible description="" name="" role="33">
+					<accessible description="" name="" role="10"/>
+					<accessible description="" name="" role="10"/>
+				</accessible>
+			</accessible>
+			<accessible description="" name="" role="35">
+				<accessible description="" name="" role="69"/>
+			</accessible>
+			<accessible description="" name="" role="35"/>
+			<accessible description="" name="" role="35"/>
+			<accessible description="" name="" role="35"/>
+			<accessible description="" name="" role="35"/>
+			<accessible description="" name="" role="35"/>
+			<accessible description="" name="" role="66"/>
+			<accessible description="" name="" role="66"/>
+			<accessible description="" name="" role="65">
+				<accessible description="" name="Application" role="36"/>
+				<accessible description="" name="" role="53"/>
+				<accessible description="" name="Activity Indicator" role="45"/>
+			</accessible>
+			<accessible description="" name="" role="65">
+				<accessible description="Go back one page" name="Back" role="45"/>
+				<accessible description="Go forwards one page" name="Forward" role="45"/>
+				<accessible description="" name="" role="45"/>
+				<accessible description="Reload current page" name="Reload" role="45"/>
+				<accessible description="Stop loading this page" name="Stop" role="45"/>
+				<accessible description="chrome://ubufox/content/startpage.html" name="Home" role="45"/>
+				<accessible description="" name="Location" role="80"/>
+				<accessible description="" name="Search using Google" role="80"/>
+			</accessible>
+			<accessible description="" name="" role="65">
+				<accessible description="" name="Smart Bookmarks" role="45"/>
+				<accessible description="" name="Getting Started" role="45"/>
+				<accessible description="" name="Latest Headlines" role="45"/>
+			</accessible>
+			<accessible description="" name="" role="41">
+				<accessible description="" name="Google Reader" role="66"/>
+				<accessible description="" name="" role="35"/>
+				<accessible description="" name="" role="40"/>
+				<accessible description="" name="" role="51"/>
+				<accessible description="" name="" role="51">
+					<accessible description="" name="Google Reader" role="30">
+						<accessible description="" name="Google Reader" role="86">
+							<accessible description="" name="Click here for ARIA enhanced Google Reader." role="72"/>
+							<accessible description="" name="" role="89"/>
+							<accessible description="" name="" role="89"/>
+							<accessible description="" name="" role="89"/>
+							<accessible description="" name="Google Reader" role="72"/>
+							<accessible description="" name="" role="63"/>
+							<accessible description="" name="" role="89"/>
+							<accessible description="" name="" role="89">
+								<accessible description="" name="" role="89"/>
+								<accessible description="" name="" role="89"/>
+								<accessible description="" name="" role="89">
+									<accessible description="" name="" role="57"/>
+									<accessible description="" name="" role="89">
+										<accessible description="" name="" role="89">
+											<accessible description="" name="" role="89">
+												<accessible description="" name="" role="57"/>
+												<accessible description="" name="" role="57">
+													<accessible description="" name="" role="58">
+														<accessible description="" name="" role="89">
+															<accessible description="" name="" role="89"/>
+															<accessible description="" name="" role="63"/>
+															<accessible description="" name="Google News" role="72"/>
+															<accessible description="" name="" role="89">
+																<accessible description="" name="" role="89"/>
+																<accessible description="" name="" role="89">
+																	<accessible description="" name="Reader and ARIA: A new way to read" role="72"/>
+																</accessible>
+																<accessible description="" name="" role="89">
+																	<accessible description="" name="Official Google Reader Blog" role="72"/>
+																</accessible>
+																<accessible description="" name="" role="89"/>
+															</accessible>
+														</accessible>
+													</accessible>
+													<accessible description="" name="" role="58"/>
+												</accessible>
+											</accessible>
+											<accessible description="" name="" role="89">
+												<accessible description="" name="Google Reader Blog" role="72"/>
+												<accessible description="" name="Discuss" role="72"/>
+												<accessible description="" name="Privacy Policy" role="72"/>
+												<accessible description="" name="Help" role="72"/>
+												<accessible description="" name="" role="89"/>
+											</accessible>
+										</accessible>
+									</accessible>
+								</accessible>
+							</accessible>
+							<accessible description="" name="" role="89">
+								<accessible description="" name="" role="29"/>
+								<accessible description="" name="" role="29"/>
+								<accessible description="" name="" role="29"/>
+								<accessible description="" name="" role="29"/>
+								<accessible description="" name="" role="29"/>
+							</accessible>
+						</accessible>
+					</accessible>
+				</accessible>
+			</accessible>
+			<accessible description="" name="" role="35"/>
+			<accessible description="" name="" role="56">
+				<accessible description="" name="Done" role="45"/>
+				<accessible description="" name="" role="45"/>
+			</accessible>
+		</accessible>
+	</accessible>
+	<accessible description="" name="gnome-terminal" role="79">
+		<accessible description="" name="mdoff@silver-wind: ~/Projects/accessibility/dbus-atspi/test" role="25"/>
+	</accessible>
+</accessible>
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/data/accessible-test.xml pyatspi2/tests/data/accessible-test.xml
--- pyatspi2.old/tests/data/accessible-test.xml	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/data/accessible-test.xml	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,157 @@
+<!--
+
+Copyright 2008 Codethink Ltd.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+
+-->
+
+<?xml version="1.0" ?>
+<accessible description="The main accessible object, root of the accessible tree" name="atspi-test-main" role="68" type="document">
+	<accessible description="" name="gnome-settings-daemon" role="77"/>
+	<accessible description="" name="gnome-panel" role="77">
+		<accessible description="" name="Bottom Expanded Edge Panel" role="24"/>
+		<accessible description="" name="Top Expanded Edge Panel" role="24"/>
+	</accessible>
+	<accessible description="" name="nautilus" role="77">
+		<accessible description="" name="Desktop" role="24"/>
+	</accessible>
+	<accessible description="" name="metacity" role="77"/>
+	<accessible description="" name="tracker-applet" role="77"/>
+	<accessible description="" name="empathy" role="77">
+		<accessible description="" name="Contact List" role="24"/>
+	</accessible>
+	<accessible description="" name="nm-applet" role="77"/>
+	<accessible description="" name="gnome-power-manager" role="77"/>
+	<accessible description="" name="update-notifier" role="77"/>
+	<accessible description="Firefox Application Accessible" name="Firefox" role="77">
+		<accessible description="Firefox Application Accessible" name="Google Reader - Mozilla Firefox 3 Beta 5" role="24">
+			<accessible description="" name="" role="34"/>
+			<accessible description="" name="Strip originally conceived in conversation with Jeph Jacques. Soon to be a major motion picture." role="65"/>
+			<accessible description="" name="" role="67">
+				<accessible description="" name="" role="32">
+					<accessible description="" name="" role="10"/>
+					<accessible description="" name="" role="10"/>
+				</accessible>
+			</accessible>
+			<accessible description="" name="" role="34">
+				<accessible description="" name="" role="68"/>
+			</accessible>
+			<accessible description="" name="" role="34"/>
+			<accessible description="" name="" role="34"/>
+			<accessible description="" name="" role="34"/>
+			<accessible description="" name="" role="34"/>
+			<accessible description="" name="" role="34"/>
+			<accessible description="" name="" role="65"/>
+			<accessible description="" name="" role="65"/>
+			<accessible description="" name="" role="64">
+				<accessible description="" name="Application" role="35"/>
+				<accessible description="" name="" role="51"/>
+				<accessible description="" name="Activity Indicator" role="44"/>
+			</accessible>
+			<accessible description="" name="" role="64">
+				<accessible description="Go back one page" name="Back" role="44"/>
+				<accessible description="Go forwards one page" name="Forward" role="44"/>
+				<accessible description="" name="" role="44"/>
+				<accessible description="Reload current page" name="Reload" role="44"/>
+				<accessible description="Stop loading this page" name="Stop" role="44"/>
+				<accessible description="chrome://ubufox/content/startpage.html" name="Home" role="44"/>
+				<accessible description="" name="Location" role="78"/>
+				<accessible description="" name="Search using Google" role="78"/>
+			</accessible>
+			<accessible description="" name="" role="64">
+				<accessible description="" name="Smart Bookmarks" role="44"/>
+				<accessible description="" name="Getting Started" role="44"/>
+				<accessible description="" name="Latest Headlines" role="44"/>
+			</accessible>
+			<accessible description="" name="" role="40">
+				<accessible description="" name="Google Reader" role="65"/>
+				<accessible description="" name="" role="34"/>
+				<accessible description="" name="" role="39"/>
+				<accessible description="" name="" role="50"/>
+				<accessible description="" name="" role="50">
+					<accessible description="" name="Google Reader" role="29">
+						<accessible description="" name="Google Reader" role="84">
+							<accessible description="" name="Click here for ARIA enhanced Google Reader." role="70"/>
+							<accessible description="" name="" role="87"/>
+							<accessible description="" name="" role="87"/>
+							<accessible description="" name="" role="87"/>
+							<accessible description="" name="Google Reader" role="70"/>
+							<accessible description="" name="" role="62"/>
+							<accessible description="" name="" role="87"/>
+							<accessible description="" name="" role="87">
+								<accessible description="" name="" role="87"/>
+								<accessible description="" name="" role="87"/>
+								<accessible description="" name="" role="87">
+									<accessible description="" name="" role="56"/>
+									<accessible description="" name="" role="87">
+										<accessible description="" name="" role="87">
+											<accessible description="" name="" role="87">
+												<accessible description="" name="" role="56"/>
+												<accessible description="" name="" role="56">
+													<accessible description="" name="" role="57">
+														<accessible description="" name="" role="87">
+															<accessible description="" name="" role="87"/>
+															<accessible description="" name="" role="62"/>
+															<accessible description="" name="Google News" role="70"/>
+															<accessible description="" name="" role="87">
+																<accessible description="" name="" role="87"/>
+																<accessible description="" name="" role="87">
+																	<accessible description="" name="Reader and ARIA: A new way to read" role="70"/>
+																</accessible>
+																<accessible description="" name="" role="87">
+																	<accessible description="" name="Official Google Reader Blog" role="70"/>
+																</accessible>
+																<accessible description="" name="" role="87"/>
+															</accessible>
+														</accessible>
+													</accessible>
+													<accessible description="" name="" role="57"/>
+												</accessible>
+											</accessible>
+											<accessible description="" name="" role="87">
+												<accessible description="" name="Google Reader Blog" role="70"/>
+												<accessible description="" name="Discuss" role="70"/>
+												<accessible description="" name="Privacy Policy" role="70"/>
+												<accessible description="" name="Help" role="70"/>
+												<accessible description="" name="" role="87"/>
+											</accessible>
+										</accessible>
+									</accessible>
+								</accessible>
+							</accessible>
+							<accessible description="" name="" role="87">
+								<accessible description="" name="" role="28"/>
+								<accessible description="" name="" role="28"/>
+								<accessible description="" name="" role="28"/>
+								<accessible description="" name="" role="28"/>
+								<accessible description="" name="" role="28"/>
+							</accessible>
+						</accessible>
+					</accessible>
+				</accessible>
+			</accessible>
+			<accessible description="" name="" role="34"/>
+			<accessible description="" name="" role="55">
+				<accessible description="" name="Done" role="44"/>
+				<accessible description="" name="" role="44"/>
+			</accessible>
+		</accessible>
+	</accessible>
+	<accessible description="" name="gnome-terminal" role="77">
+		<accessible description="" name="mdoff@silver-wind: ~/Projects/accessibility/dbus-atspi/test" role="24"/>
+	</accessible>
+</accessible>
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/data/Makefile.am pyatspi2/tests/data/Makefile.am
--- pyatspi2.old/tests/data/Makefile.am	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/data/Makefile.am	2019-08-26 23:04:09.541759565 +0200
@@ -0,0 +1,3 @@
+EXTRA_DIST = \
+	accessible-test.xml\
+	accessible-test-results.xml
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/Makefile.am pyatspi2/tests/dummyatk/Makefile.am
--- pyatspi2.old/tests/dummyatk/Makefile.am	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/Makefile.am	2019-08-26 23:04:09.541759565 +0200
@@ -0,0 +1,40 @@
+check_LTLIBRARIES = libdummyatk.la
+
+libdummyatk_la_CFLAGS = $(ATK_CFLAGS)	\
+		        -I$(top_srcdir)
+
+libdummyatk_la_LDFLAGS = -no-undefined	\
+		         -module	\
+		         -avoid-version 
+
+libdummyatk_la_LIBADD = $(ATK_LIBS)
+
+libdummyatk_la_SOURCES = my-atk-action.c		\
+			 my-atk-action.h		\
+			 my-atk-component.c		\
+			 my-atk-component.h		\
+	my-atk-document.c \
+	my-atk-document.h \
+			 my-atk-hyperlink.c		\
+			 my-atk-hyperlink.h		\
+			 my-atk-hypertext.c		\
+			 my-atk-hypertext.h		\
+			 my-atk-object.c		\
+			 my-atk-object.h		\
+			 my-atk-selection.c		\
+			 my-atk-selection.h		\
+			 my-atk-streamable-content.c	\
+			 my-atk-streamable-content.h	\
+			 my-atk-table.c			\
+			 my-atk-table.h			\
+			 my-atk-text.c			\
+			 my-atk-text.h			\
+			 my-atk-value.c			\
+			 my-atk-value.h			\
+			 my-atk.h			\
+			 resources_storage.c		\
+			 resources_storage.h		\
+			 useful_functions.c		\
+			 useful_functions.h		\
+			 user_marshal.c			\
+			 user_marshal.h
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-action.c pyatspi2/tests/dummyatk/my-atk-action.c
--- pyatspi2.old/tests/dummyatk/my-atk-action.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-action.c	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <atk/atk.h>
+
+#include "my-atk-object.h"
+#include "my-atk-action.h"
+
+static GObjectClass *parent_class = NULL;
+//implementation of the interface
+static gboolean my_atk_action_do_action(AtkAction *action, gint i)
+{
+    MyAtkAction *self = (MyAtkAction*)action;
+    gboolean result = (i>=0) && (i < self->n);
+    self->last_performed_action = result? i : -1;
+    return result;
+}
+static gint my_atk_action_get_n_actions(AtkAction *action)
+{
+    MyAtkAction *self = (MyAtkAction*)action;
+    return self->n;
+}
+static const gchar* my_atk_action_get_description(AtkAction *action, gint i)
+{
+    MyAtkAction *self = (MyAtkAction*)action;
+    if((i>=0) && (i<self->n))
+    {
+         return self->actions[i].description;
+    }
+    else
+    {
+        printf("get_description: Wrong index.\n");
+        return NULL;
+    }
+}
+static const gchar* my_atk_action_get_name(AtkAction *action, gint i)
+{
+    MyAtkAction *self = (MyAtkAction*)action;
+    if((i >= 0) && (i < self->n))
+    {
+         return self->actions[i].name;
+    }
+    else
+    {
+        printf("get_name: Wrong index.\n");
+        return NULL;
+    }
+}
+static const gchar* my_atk_action_get_localized_name(AtkAction *action, gint i)
+{
+    return my_atk_action_get_name(action,i);
+}
+
+static const gchar* my_atk_action_get_keybinding(AtkAction *action, gint i)
+{
+    MyAtkAction *self = (MyAtkAction*)action;
+    if((i >= 0) && (i < self->n))
+    {
+        gchar* keyb = self->actions[i].keybinding;
+        if(keyb == NULL || keybinding_note_define == NULL)
+        {
+            //anywhere(if action has keybinding or not) NULL will return
+            return NULL;
+        }
+        else
+        {
+            //verify, if string mean "no keybinding"
+            return strcmp(keyb, keybinding_note_define) != 0 ? keyb : NULL;
+        }
+    }
+    else
+    {
+        printf("get_keybinding: Wrong index.\n");
+        return NULL;
+    }
+}
+static gboolean my_atk_action_set_description(AtkAction *action, gint i, const gchar *desc)
+{
+    MyAtkAction *self = (MyAtkAction*)action;
+
+    if(!((i >= 0) && (i < self->n)) )
+    {
+        //index out of range, but this is not application error according documentation
+        return FALSE;
+    }
+    //index in correct range
+    if(self->actions[i].description == desc)
+    {
+        //self assignment - return immediately
+        return TRUE;
+    }
+    if(self->actions[i].description != NULL)
+    {
+        //free old value of description if it is not NULL
+        free(self->actions[i].description);
+    }
+    if(desc != NULL)
+    {
+        //dump new value of description if it is not NULL
+        self->actions[i].description = (gchar*)strdup((const char*)desc);
+    }
+    return TRUE;
+}
+//////////
+static void my_atk_action_instance_init(GTypeInstance *instance, gpointer g_class)
+{
+  int i;
+    MyAtkAction *self = (MyAtkAction*)instance;
+    self->n = DEFAULT_NUMBER_ACTIONS;
+    self->actions = g_new(struct OneAction, self->n);
+    if(self->actions == NULL)
+    {
+        self->n = 0;
+        return;
+    }
+    //init fields of action 0 with values which differ from others actions
+    self->actions[0].name = (gchar*)strdup(FIRST_ACTION_NAME);
+    self->actions[0].description = (gchar*)strdup(FIRST_ACTION_DESCRIPTION);
+    self->actions[0].keybinding = (gchar*)strdup(FIRST_ACTION_KEYBINDING);
+
+    for(i = 1; i < self->n; i++)
+    {
+        self->actions[i].name = (gchar*)strdup(DEFAULT_ACTION_NAME);
+        self->actions[i].description = (gchar*)strdup(DEFAULT_ACTION_DESCRIPTION);
+        self->actions[i].keybinding = g_strdup_printf("%d", i);
+    }
+    self->disposed = FALSE;
+    self->last_performed_action = -1;
+}
+
+static void
+my_atk_action_interface_init(gpointer g_iface, gpointer iface_data)
+{
+    AtkActionIface *klass = (AtkActionIface *)g_iface;
+
+    klass->do_action = my_atk_action_do_action;
+    klass->get_n_actions = my_atk_action_get_n_actions;
+    klass->get_description = my_atk_action_get_description;
+    klass->get_name = my_atk_action_get_name;
+    klass->get_localized_name = my_atk_action_get_localized_name;
+    klass->get_keybinding = my_atk_action_get_keybinding;
+    klass->set_description = my_atk_action_set_description;
+}
+
+static void
+my_atk_action_dispose(GObject *obj)
+{
+    MyAtkAction *self = (MyAtkAction*)obj;
+
+    if(self->disposed)
+    {
+        return;
+    }
+    self->disposed = TRUE;
+
+    G_OBJECT_CLASS(parent_class)->dispose(obj);
+}
+
+static void 
+my_atk_action_finalize(GObject *obj)
+{
+    MyAtkAction *self = (MyAtkAction*)obj;
+  int i;
+
+    for(i = 0; i < self->n; i++)
+    {
+        struct OneAction oneAction = self->actions[i];
+        if(oneAction.name != NULL)
+            free(oneAction.name);
+        if(oneAction.description != NULL)
+            free(oneAction.description);
+        if(oneAction.keybinding != NULL)
+            free(oneAction.keybinding);
+    }
+    if(self->actions != NULL)
+        g_free(self->actions);
+
+    G_OBJECT_CLASS(parent_class)->finalize(obj);
+}
+static void
+my_atk_action_class_init (gpointer g_class, gpointer g_class_data)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS(g_class);
+    MyAtkActionClass *klass = MY_ATK_ACTION_CLASS (g_class);
+
+    gobject_class->dispose = my_atk_action_dispose;
+    gobject_class->finalize = my_atk_action_finalize;
+
+    parent_class = g_type_class_peek_parent(klass);
+}
+GType my_atk_action_get_type(void)
+{
+    static GType type = 0;
+    if(type == 0)
+    {
+        static const GTypeInfo info =
+        {
+            sizeof (MyAtkActionClass),
+            NULL,   /* base_init */
+            NULL,   /* base_finalize */
+            my_atk_action_class_init, /* class_init */
+            NULL,   /* class_finalize */
+            NULL,   /* class_data */
+            sizeof (MyAtkAction),
+            0,      /* n_preallocs */
+            my_atk_action_instance_init    /* instance_init */
+        };
+
+        static const GInterfaceInfo iface_info = 
+        {
+            (GInterfaceInitFunc) my_atk_action_interface_init,    /* interface_init */
+            NULL,                                       /* interface_finalize */
+            NULL                                        /* interface_data */
+        };
+        type = g_type_register_static (MY_TYPE_ATK_OBJECT,
+            "MyAtkAction",
+            &info, 0);
+        g_type_add_interface_static (type,
+            ATK_TYPE_ACTION,
+            &iface_info);
+    }
+    return type;
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-action.h pyatspi2/tests/dummyatk/my-atk-action.h
--- pyatspi2.old/tests/dummyatk/my-atk-action.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-action.h	2019-08-27 19:10:03.869588504 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MY_ATK_ACTION_H
+#define MY_ATK_ACTION_H
+//Object, which implement interface AtkAction(all functions)
+#include <glib.h>
+#include <glib-object.h>
+#include <atk/atk.h>
+
+#include "my-atk-object.h"
+
+//declarations
+#define MY_TYPE_ATK_ACTION             (my_atk_action_get_type ())
+#define MY_ATK_ACTION(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_ATK_ACTION, MyAtkAction))
+#define MY_ATK_ACTION_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MY_TYPE_ATK_ACTION, MyAtkActionClass))
+#define MY_IS_ATK_ACTION(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_ATK_ACTION))
+#define MY_IS_ATK_ACTION_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MY_TYPE_ATK_ACTION))
+#define MY_ATK_ACTION_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MY_TYPE_ATK_ACTION, MyAtkActionClass))
+
+static const gchar* keybinding_note_define = "none";
+
+#define FIRST_ACTION_NAME "First action"
+#define FIRST_ACTION_DESCRIPTION "First action performed"
+#define FIRST_ACTION_KEYBINDING "0"
+
+#define DEFAULT_NUMBER_ACTIONS 10
+#define DEFAULT_ACTION_NAME "Action"
+#define DEFAULT_ACTION_DESCRIPTION "Description of action"
+#define DEFAULT_ACTION_KEYBINDING keybinding_note_define
+
+
+//for external using
+#define LAST_PERFORMED_ACTION(myAtkAction) (MY_ATK_ACTION(myAtkAction)->last_performed_action)
+#define CLEAR_LAST_PERFOMED_ACTION(myAtkAction) (MY_ATK_ACTION(myAtkAction)->last_performed_action = -1
+
+typedef struct _MyAtkAction MyAtkAction;
+typedef struct _MyAtkActionClass MyAtkActionClass;
+
+struct _MyAtkAction
+{
+    MyAtkObject parent;
+
+    gboolean disposed;
+    struct OneAction
+    {
+        gchar *name;
+        gchar *description;
+        gchar *keybinding;
+    }*actions;
+    gint n;
+    gint last_performed_action;//this field is changed when perfoms action
+};
+
+struct _MyAtkActionClass
+{
+    MyAtkObjectClass parent;
+};
+GType my_atk_action_get_type(void);
+
+#endif /*MY_ATK_ACTION_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-component.c pyatspi2/tests/dummyatk/my-atk-component.c
--- pyatspi2.old/tests/dummyatk/my-atk-component.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-component.c	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,422 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <atk/atk.h>
+#include <limits.h>
+
+#include "my-atk-object.h"
+#include "my-atk-component.h"
+
+//*************************implementation***********************
+static MyAtkObjectClass *component_parent_class = NULL;
+//current focus object
+static AtkComponent* focus_object = NULL;
+
+static guint focus_signal_id = 0;
+/*
+ * Because of implementation of AtkUtils, we need to ensure that list of focus_trackers 
+ * is not empty. Otherwise function atk_focus_tracker_notify will not change focus.
+ */
+static guint focus_tracker_id = 0;
+static void my_event_listener(AtkObject* obj)
+{
+    //simply exist for register as focus_tracker
+}
+/*
+ * If this flag is TRUE, then focus cannot be changed until someone clears the flag
+ * via my_atk_component_set_modal(FALSE).
+ */
+static gboolean is_modal = FALSE;
+//for debug
+void print_extent(AtkRectangle *extent)
+{
+    printf("{%d,%d,%d,%d}", extent->x, extent->y, extent->width, extent->height);
+}
+//for internal use
+static void emit_bounds_changed(MyAtkComponent *component)
+{
+    static guint bounds_changed_id = 0;
+    if(bounds_changed_id == 0)
+    {
+        bounds_changed_id = g_signal_lookup("bounds-changed", ATK_TYPE_COMPONENT);
+    }
+    AtkRectangle *param = g_boxed_copy(ATK_TYPE_RECTANGLE, &(component->extent));
+    g_signal_emit(component, bounds_changed_id, 0, param);
+}
+static void change_focus(AtkComponent* component, gboolean is_gain)
+{
+    const gchar* state_name = atk_state_type_get_name(ATK_STATE_FOCUSED);
+    
+    g_signal_emit_by_name(component, "focus-event", is_gain);
+    g_signal_emit_by_name(component, "state-change::focused",
+        state_name, is_gain);
+    
+    AtkObject* parent = atk_object_get_parent((AtkObject*)component);
+    if(parent != NULL)
+    {
+        AtkStateSet* stateSet = atk_object_ref_state_set(parent);
+        if(atk_state_set_contains_state(stateSet, ATK_STATE_MANAGES_DESCENDANTS))
+            g_signal_emit_by_name(parent, "active-descendant-changed",
+                atk_get_focus_object());
+        g_object_unref(stateSet);
+    }
+}
+//implementation of virtual functions
+//******************ref_state_set(AtkObject)*****************************
+static AtkStateSet* my_atk_component_ref_state_set(AtkObject *object)
+{
+    MyAtkComponent *self = (MyAtkComponent*)object;
+    
+    AtkStateSet* result = ((AtkObjectClass*)component_parent_class)->
+        ref_state_set(object);
+    if(self->is_manage_descendants) 
+        atk_state_set_add_state(result, ATK_STATE_MANAGES_DESCENDANTS);
+    return result;
+}
+//******************get_size*******************
+static void my_atk_component_get_size(AtkComponent *component, gint *width, gint *height)
+{
+    g_return_if_fail(MY_IS_ATK_COMPONENT(component));
+    
+    MyAtkComponent *self = MY_ATK_COMPONENT(component);
+    *width = self->extent.width;
+    *height = self->extent.height;
+}
+//*********************get_position*******************
+static void my_atk_component_get_position(AtkComponent *component, gint *x, gint *y, AtkCoordType coord_type)
+{
+    g_return_if_fail(MY_IS_ATK_COMPONENT(component));
+    
+    MyAtkComponent *self = MY_ATK_COMPONENT(component);
+    *x = self->extent.x;
+    *y = self->extent.y;
+    
+//**********************get_extents*******************
+}
+static void my_atk_component_get_extents(AtkComponent *component, gint *x, gint *y,
+    gint *width, gint *height, AtkCoordType coord_type)
+{
+    g_return_if_fail(MY_IS_ATK_COMPONENT(component));
+    
+    MyAtkComponent *self = MY_ATK_COMPONENT(component);
+    *x = self->extent.x;
+    *y = self->extent.y;
+    *width = self->extent.width;
+    *height = self->extent.height;
+}
+
+//**************************set_size*******************
+static gboolean my_atk_component_set_size(AtkComponent *component, gint width, gint height)
+{
+    g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
+    
+    MyAtkComponent *self = MY_ATK_COMPONENT(component);
+    if(self->is_extent_may_changed)
+    {
+        self->extent.width = width;
+        self->extent.height = height;
+    
+        emit_bounds_changed(self);
+        
+        return TRUE;
+    }
+    return FALSE;
+}
+//**************************set_position********************
+static gboolean my_atk_component_set_position(AtkComponent *component,
+    gint x, gint y, AtkCoordType coord_type)
+{
+    g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
+    
+    MyAtkComponent *self = MY_ATK_COMPONENT(component);
+    if(self->is_extent_may_changed)
+    {
+        self->extent.x = x;
+        self->extent.y = y;
+        
+        emit_bounds_changed(self);
+
+        return TRUE;
+    }
+    return FALSE;
+}
+//*************************************set_extents***************
+static gboolean my_atk_component_set_extents(AtkComponent *component,
+    gint x, gint y, gint width, gint height, AtkCoordType coord_type)
+{
+    g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
+    
+    MyAtkComponent *self = MY_ATK_COMPONENT(component);
+    
+    if(self->is_extent_may_changed)
+    {
+        self->extent.x = x;
+        self->extent.y = y;
+        self->extent.width = width;
+        self->extent.height = height;
+        
+        emit_bounds_changed(self);
+        
+        return TRUE;
+    }
+    return FALSE;
+}
+//**************************get_layer****************
+static AtkLayer my_atk_component_get_layer(AtkComponent *component)
+{
+    g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), ATK_LAYER_INVALID);
+    
+    MyAtkComponent *self = MY_ATK_COMPONENT(component);
+    return self->layer;
+}
+//**************************get_mdi_zorder****************
+static gint my_atk_component_get_mdi_zorder(AtkComponent *component)
+{
+    g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), G_MININT);
+    
+    MyAtkComponent *self = MY_ATK_COMPONENT(component);
+    return self->zorder;
+}
+//***********************contains**********************
+static gboolean my_atk_component_contains(AtkComponent *component,
+    gint x, gint y, AtkCoordType coord_type)
+{
+    g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
+    //for extract extent
+    gint x_tmp, y_tmp, width_tmp, height_tmp;
+    my_atk_component_get_extents(component, &x_tmp, &y_tmp, &width_tmp, &height_tmp, coord_type);
+    
+    if( (x >= x_tmp) &&(y >= y_tmp) &&(x < x_tmp + width_tmp) && (y < y_tmp + height_tmp) )
+    {
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+//**********************ref_accessible_at_point***********************
+/*
+ * Retuns accessible child that implements AtkCOmponent and contains the given point.
+ */
+static AtkObject* my_atk_component_ref_accessible_at_point(AtkComponent* component,
+    gint x, gint y, AtkCoordType coord_type)
+{
+    g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), NULL);
+    gint i;
+    
+    gint n_children = atk_object_get_n_accessible_children((AtkObject*)component);
+    for(i = 0; i < n_children; i++)
+    {
+        AtkObject *child = atk_object_ref_accessible_child((AtkObject*)component, i);
+        if(ATK_IS_COMPONENT(child)
+            && atk_component_contains((AtkComponent*)child, x, y, coord_type))
+        {
+            return child;
+        }
+        g_object_unref(child);
+    }
+    return NULL;
+}
+//*************************************grab_focus*********************************
+static gboolean my_atk_component_grab_focus(AtkComponent* component)
+{
+    if(component == focus_object)
+    { 
+        //Already has focus
+        return TRUE;
+    }
+    if(is_modal)
+    {
+        //cannot grab focus
+        return FALSE;
+    }
+    AtkComponent *focus_object_old = focus_object;
+    focus_object = component;
+    
+    atk_focus_tracker_notify((AtkObject*)component);
+    
+    if(focus_object_old != NULL)
+    {
+        //signals for object which lost focus
+        change_focus(focus_object_old, FALSE);
+    }
+    if(component != NULL)
+    {
+        //signals for object which grab focus
+        change_focus(component, TRUE);
+    }
+    return TRUE;
+}
+//***********************my_atk_component_add_focus_handler*********************
+static guint my_atk_component_add_focus_handler(AtkComponent *component, AtkFocusHandler handler)
+{
+    g_return_val_if_fail(MY_IS_ATK_COMPONENT(component),0);
+    //verify whether handler already connect to object
+    gulong found_handler_id = g_signal_handler_find(component,
+        G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC,
+        focus_signal_id,
+        0,
+        NULL,
+        (gpointer)handler,
+        NULL);
+    if(found_handler_id == 0)
+    {
+        //handler hasn't been connected yet
+        return g_signal_connect_closure_by_id(component,
+            focus_signal_id,
+            0,
+            g_cclosure_new( (GCallback)handler,
+                NULL,
+                NULL),
+            FALSE);
+    }
+    else/* found_handler_id != 0*/
+    {
+        //handler has already been connected
+        return 0;
+    }
+
+}
+//***********************my_atk_component_remove_focus_handler*********************
+static void my_atk_component_remove_focus_handler(AtkComponent *component, guint handler_id)
+{
+    g_signal_handler_disconnect(component, handler_id);
+}
+//***********************my_atk_component_set_modal(my function)***************
+void my_atk_component_set_modal(gboolean value)
+{
+    is_modal = value;
+}
+//******************my_atk_component_set_manage_descendants(my_function)*******
+void my_atk_component_set_manage_descendants(MyAtkComponent* component, gboolean value)
+{
+    if(component->is_manage_descendants == value)return;
+    component->is_manage_descendants = value;
+    g_signal_emit_by_name(component, "state-change::manages-descendants",
+        "manages-descendants", value);
+}
+//Others funtions
+static void my_atk_component_instance_init(GTypeInstance *obj, gpointer g_class)
+{
+    MyAtkComponent *self = (MyAtkComponent*)obj;
+    //set defaults values
+    self->extent.x = 0;
+    self->extent.y = 0;
+    self->extent.width = 10;
+    self->extent.height = 10;
+    self->is_extent_may_changed = TRUE;
+    self->layer = ATK_LAYER_INVALID;
+    self->zorder = -2147;
+}
+static void my_atk_component_instance_finalize(GObject* obj)
+{
+    MyAtkComponent* component = (MyAtkComponent*)obj;
+
+    if(((AtkObject*)component) == atk_get_focus_object())
+    {
+        atk_focus_tracker_notify(NULL);
+    }
+}
+
+static void my_atk_component_class_init(gpointer g_class, gpointer class_data)
+{
+    GObjectClass* g_object_class = (GObjectClass*)g_class;
+    AtkObjectClass* atkObject_class = (AtkObjectClass*)g_class;
+    //GObject virtual table
+    g_object_class->finalize = my_atk_component_instance_finalize;
+    //AtkObject virtual table
+    atkObject_class->ref_state_set = my_atk_component_ref_state_set;
+    //parent_class
+    component_parent_class = g_type_class_peek_parent(g_class);
+    //make focus_tracker's table not empty.
+    focus_tracker_id = atk_add_focus_tracker(my_event_listener);
+    //store "focus-event"-signal id
+    focus_signal_id = g_signal_lookup("focus-event",MY_TYPE_ATK_COMPONENT);
+}
+/*
+ * Though, according to the documentation, this function will never called for 
+ * static-registred types.
+ * Base_init function doesn't suite for this work,
+ * because it will called in every derived classes.
+ */
+/*static void my_atk_component_class_finalize(gpointer g_class, gpointer class_data)
+{
+    
+    if(focus_tracker_id != 0)
+    {
+        atk_remove_focus_tracker(focus_tracker_id);
+        focus_tracker_id = 0;
+    }
+}*/
+static void my_atk_component_interface_init(gpointer g_iface, gpointer iface_data)
+{
+    AtkComponentIface *klass = (AtkComponentIface*)g_iface;
+    
+    klass->get_extents = my_atk_component_get_extents;
+    klass->get_position = my_atk_component_get_position;
+    klass->get_size = my_atk_component_get_size;
+    
+    klass->set_extents = my_atk_component_set_extents;
+    klass->set_position = my_atk_component_set_position;
+    klass->set_size = my_atk_component_set_size;
+    
+    klass->contains = my_atk_component_contains;
+    klass->ref_accessible_at_point = my_atk_component_ref_accessible_at_point;
+    
+    klass->get_layer = my_atk_component_get_layer;
+    klass->get_mdi_zorder = my_atk_component_get_mdi_zorder;
+    
+    klass->grab_focus = my_atk_component_grab_focus;
+    klass->add_focus_handler = my_atk_component_add_focus_handler;
+    klass->remove_focus_handler = my_atk_component_remove_focus_handler;
+}
+
+GType my_atk_component_get_type()
+{
+    static GType type = 0;
+    if(type == 0)
+    {
+        static const GTypeInfo typeInfo = 
+        {
+            sizeof(MyAtkComponentClass),
+            NULL, //base_init
+            NULL, //base_finalize
+            my_atk_component_class_init, //class_init
+            NULL, //class_finalize
+            NULL, //class_data
+            sizeof(MyAtkComponent),
+            0, //n_preallocs
+            my_atk_component_instance_init //instance_init
+        };
+
+        static const GInterfaceInfo iface_info = 
+        {
+            my_atk_component_interface_init,    /* interface_init*/
+            NULL,                               /* interface_finalize*/
+            NULL                                /* interface_data */
+        };
+        type = g_type_register_static(MY_TYPE_ATK_OBJECT, "MyAtkComponent", &typeInfo, 0);
+        g_type_add_interface_static(type,
+            ATK_TYPE_COMPONENT,
+            &iface_info);
+    }
+    return type;    
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-component.h pyatspi2/tests/dummyatk/my-atk-component.h
--- pyatspi2.old/tests/dummyatk/my-atk-component.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-component.h	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MY_ATK_COMPONENT_H
+#define MY_ATK_COMPONENT_H
+/*
+ * MyAtkComponent: derives AtkObject(with parent-child accessibilities)
+ * and implements AtkComponent.
+ */
+#include <atk/atk.h>
+
+#include "my-atk-object.h"
+
+#define MY_TYPE_ATK_COMPONENT             (my_atk_component_get_type ())
+#define MY_ATK_COMPONENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_ATK_COMPONENT, MyAtkComponent))
+#define MY_ATK_COMPONENT_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MY_TYPE_ATK_COMPONENT, MyAtkComponentClass))
+#define MY_IS_ATK_COMPONENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_ATK_COMPONENT))
+#define MY_IS_ATK_COMPONENT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MY_TYPE_ATK_COMPONENT))
+#define MY_ATK_COMPONENT_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MY_TYPE_ATK_COMPONENT, MyAtkComponentClass))
+
+typedef struct _MyAtkComponent MyAtkComponent;
+typedef struct _MyAtkComponentClass MyAtkComponentClass;
+
+struct _MyAtkComponent
+{
+    MyAtkObject parent;
+    //relative coordinates, which coincides with absolute ones
+    AtkRectangle extent;
+    //whether component may be relocated
+    gboolean is_extent_may_changed;
+    //for emit "active-descendant-changed" signal
+    gboolean is_manage_descendants;
+    //
+    AtkLayer layer;
+    gint zorder;
+};
+
+struct _MyAtkComponentClass
+{
+    MyAtkObjectClass parent;
+};
+
+GType my_atk_component_get_type();
+#endif /*MY_ATK_COMPONENT_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-document.c pyatspi2/tests/dummyatk/my-atk-document.c
--- pyatspi2.old/tests/dummyatk/my-atk-document.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-document.c	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2010 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* This file contains both declaration and definition of the MyAtkDocument,
+ * a GObject that pretends to implement the AtkDocumentIface interface (it 
+ * registers appropriate interface), but provides no implementation for any of the
+ * methods of this interface (NULL-filled vftbl).
+ */
+
+#include <glib-object.h>
+#include <atk/atk.h> 
+
+#include "my-atk-object.h"
+#include "my-atk-document.h"
+    
+///////////////////////////////////////////////////////////////////////////
+// Helper functions and data
+///////////////////////////////////////////////////////////////////////////
+const gchar *
+my_atk_document_get_document_locale (AtkDocument *document)
+{
+  return DEF_LOCALE_TEXT;
+}
+
+const gchar *
+my_atk_document_get_document_type (AtkDocument *document)
+{
+  return DEF_TYPE_TEXT;
+}
+
+AtkAttributeSet *
+my_atk_document_get_document_attributes (AtkDocument *document)
+{
+  /* TODO: Implement */
+  return NULL;
+}
+
+const gchar *
+my_atk_document_get_document_attribute_value (AtkDocument *document, const gchar *value)
+{
+  /*( TODO: Implement */
+  return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Implementation
+///////////////////////////////////////////////////////////////////////////
+static GObjectClass *parent_class_document = NULL;
+
+/******************************************************************/
+static void
+document_interface_init (gpointer g_iface, gpointer iface_data)
+{
+    AtkDocumentIface *klass = (AtkDocumentIface *)g_iface;
+    
+    /* set up overrides here */
+    klass-> get_document_type = my_atk_document_get_document_type;
+    klass-> get_document_locale = my_atk_document_get_document_locale;
+    klass-> get_document_attributes = my_atk_document_get_document_attributes;
+    klass-> get_document_attribute_value = my_atk_document_get_document_attribute_value;
+}
+
+static void
+document_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+    MyAtkDocument *self = (MyAtkDocument *)instance;
+    
+    self->disposed = FALSE;
+}
+
+static void
+my_atk_document_dispose (GObject *obj)
+{
+    MyAtkDocument *self = (MyAtkDocument *)obj;
+
+    if (self->disposed) 
+    {
+        return;
+    }
+    
+    /* Make sure dispose does not run twice. */
+    self->disposed = TRUE;
+
+    /* Chain up to the parent class */
+    G_OBJECT_CLASS (parent_class_document)->dispose (obj);
+}
+
+static void
+my_atk_document_finalize (GObject *obj)
+{
+    /* Chain up to the parent class */
+    G_OBJECT_CLASS (parent_class_document)->finalize (obj);
+}
+
+static void
+my_atk_document_class_init (gpointer g_class, gpointer g_class_data)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
+    MyAtkDocumentClass *klass = MY_ATK_DOCUMENT_CLASS (g_class);
+
+    gobject_class->dispose = my_atk_document_dispose;
+    gobject_class->finalize = my_atk_document_finalize;
+
+    parent_class_document = g_type_class_peek_parent (klass);
+}
+
+GType 
+my_atk_document_get_type (void)
+{
+    static GType type = 0;
+    if (type == 0) 
+    {
+        static const GTypeInfo info = 
+        {
+            sizeof (MyAtkDocumentClass),
+            NULL,   /* base_init */
+            NULL,   /* base_finalize */
+            my_atk_document_class_init, /* class_init */
+            NULL,   /* class_finalize */
+            NULL,   /* class_data */
+            sizeof (MyAtkDocument),
+            0,      /* n_preallocs */
+            document_instance_init    /* instance_init */
+        };
+                
+        static const GInterfaceInfo iface_info = 
+        {
+            (GInterfaceInitFunc) document_interface_init,    /* interface_init */
+            NULL,                                       /* interface_finalize */
+            NULL                                        /* interface_data */
+        };
+        type = g_type_register_static (MY_TYPE_ATK_OBJECT,
+                                       "MyAtkDocumentType",
+                                       &info, 0);
+        g_type_add_interface_static (type,
+                                     ATK_TYPE_DOCUMENT,
+                                     &iface_info);
+    }
+    return type;
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-document.h pyatspi2/tests/dummyatk/my-atk-document.h
--- pyatspi2.old/tests/dummyatk/my-atk-document.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-document.h	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MY_ATK_DOCUMENT_H
+#define MY_ATK_DOCUMENT_H
+
+#include <glib-object.h>
+#include <atk/atk.h> 
+#include <my-atk-object.h>
+    
+#define MY_TYPE_ATK_DOCUMENT             (my_atk_document_get_type ())
+#define MY_ATK_DOCUMENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_ATK_DOCUMENT, MyAtkDocument))
+#define MY_ATK_DOCUMENT_CLASS(vdocument)    (G_TYPE_CHECK_CLASS_CAST ((vdocument), MY_TYPE_ATK_DOCUMENT, MyAtkDocumentClass))
+#define MY_IS_ATK_DOCUMENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_ATK_DOCUMENT))
+#define MY_IS_ATK_DOCUMENT_CLASS(vdocument) (G_TYPE_CHECK_CLASS_TYPE ((vdocument), MY_TYPE_ATK_DOCUMENT))
+#define MY_ATK_DOCUMENT_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MY_TYPE_ATK_DOCUMENT, MyAtkDocumentClass))
+
+// default string values
+#define DEF_LOCALE_TEXT  "en-US"
+#define DEF_TYPE_TEXT    "default type"
+
+typedef struct _MyAtkDocument MyAtkDocument;
+typedef struct _MyAtkDocumentClass MyAtkDocumentClass;
+
+struct _MyAtkDocument 
+{
+    MyAtkObject parent;
+        
+    gboolean disposed;
+    
+  gchar *locale;
+  gchar *document_type;
+};
+
+struct _MyAtkDocumentClass 
+{
+    MyAtkObjectClass parent;
+};
+
+GType 
+my_atk_document_get_type (void);
+
+#endif /*MY_ATK_DOCUMENT_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk.h pyatspi2/tests/dummyatk/my-atk.h
--- pyatspi2.old/tests/dummyatk/my-atk.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk.h	2019-08-27 19:10:03.877588542 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MY_ATK_H
+#define MY_ATK_H
+
+#include <my-atk-action.h>
+#include <my-atk-component.h>
+#include <my-atk.h>
+#include <my-atk-document.h>
+#include <my-atk-hyperlink.h>
+#include <my-atk-hypertext.h>
+#include <my-atk-object.h>
+#include <my-atk-streamable-content.h>
+#include <my-atk-text.h>
+#include <my-atk-value.h>
+
+#endif /*MY_ATK_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-hyperlink.c pyatspi2/tests/dummyatk/my-atk-hyperlink.c
--- pyatspi2.old/tests/dummyatk/my-atk-hyperlink.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-hyperlink.c	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <atk/atk.h>
+
+#include "my-atk-text.h"
+#include "my-atk-hyperlink.h"
+#include "resources_storage.h"
+
+//***************************implementation****************************************
+static MyAtkTextClass *parent_class_atk_hyperlink = NULL;
+
+// Implementation of virtual functions
+//***************************my_atk_hyperlink_get_uri**************
+gchar* my_atk_hyperlink_get_uri(AtkHyperlink* link_, gint index)
+{
+    MyAtkHyperlink* self = (MyAtkHyperlink*)link_;
+    
+    if(index < 0 || index >= self->number_of_anchors) return NULL;
+    return g_strdup(self->uri);
+}
+//**************************my_atk_hyperlink_is_valid**************************
+gboolean my_atk_hyperlink_is_valid(AtkHyperlink* link_)
+{
+    MyAtkHyperlink* self = (MyAtkHyperlink*)link_;
+    
+    return (resource_storage_get(self->uri) != NULL);
+}
+//*************************my_atk_hyperlink_get_object************************
+AtkObject* my_atk_hyperlink_get_object(AtkHyperlink* link_, gint index)
+{
+    MyAtkHyperlink* self = (MyAtkHyperlink*)link_;
+    
+    if(index < 0 || index >= self->number_of_anchors) return NULL;
+    return resource_storage_get(self->uri);
+}
+//***************************my_atk_hyperlink_get_start_index**************
+gint my_atk_hyperlink_get_start_index(AtkHyperlink* link_)
+{
+    MyAtkHyperlink* self = (MyAtkHyperlink*)link_;
+    
+    return self->start_index;
+}
+//***************************my_atk_hyperlink_get_end_index**************
+gint my_atk_hyperlink_get_end_index(AtkHyperlink* link_)
+{
+    MyAtkHyperlink* self = (MyAtkHyperlink*)link_;
+    
+    return self->end_index;
+}
+//***************************my_atk_hyperlink_link_state*******************
+guint my_atk_hyperlink_link_state(AtkHyperlink* link_)
+{
+    return 0;
+}
+//***************************my_atk_hyperlink_get_n_anchors*******************
+gboolean my_atk_hyperlink_get_n_anchors(AtkHyperlink* link_)
+{
+    return ((MyAtkHyperlink*)link_)->number_of_anchors;
+}
+//***************************my_atk_hypertlink_is_selected_link***********
+gboolean my_atk_hyperlink_is_selected_link(AtkHyperlink* link_)
+{
+    MyAtkHyperlink* self = (MyAtkHyperlink*)link_;
+    
+    return self->is_selected;
+}
+//others functions
+MyAtkHyperlink* my_atk_hyperlink_new(gint start_index, gint end_index,const gchar* uri)
+{
+    MyAtkHyperlink* result = g_object_new(MY_TYPE_ATK_HYPERLINK, NULL);
+    if(result == NULL) return NULL;
+    result->start_index = start_index;
+    result->end_index = end_index;
+    result->uri = g_strdup(uri);
+    result->number_of_anchors = 1;
+    return result;
+}
+void my_atk_hyperlink_activate(MyAtkHyperlink* hyperlink)
+{
+    g_signal_emit_by_name(hyperlink, "link-activated");
+}
+//initialize/finalize functions
+static void my_atk_hyperlink_instance_init(GTypeInstance *obj, gpointer g_class)
+{
+    MyAtkHyperlink *self = (MyAtkHyperlink*)obj;
+    
+    self->start_index = self->end_index = 0;
+    self->uri = NULL;
+    self->is_selected = FALSE;
+    self->number_of_anchors = 0;
+}
+static void my_atk_hyperlink_instance_finalize(GObject* obj)
+{
+    MyAtkHyperlink *self = (MyAtkHyperlink*)obj;
+    
+    g_free(self->uri);
+}
+
+static void my_atk_hyperlink_class_init(gpointer g_class, gpointer class_data)
+{
+    GObjectClass* g_object_class = (GObjectClass*)g_class;
+    //GObject virtual table
+    g_object_class->finalize = my_atk_hyperlink_instance_finalize;
+    //parent_class
+    parent_class_atk_hyperlink = g_type_class_peek_parent(g_class);
+    //
+    AtkHyperlinkClass* atkHyperlinkClass = (AtkHyperlinkClass*)g_class;
+    
+    atkHyperlinkClass->get_uri = my_atk_hyperlink_get_uri;
+    atkHyperlinkClass->get_object = my_atk_hyperlink_get_object;
+    atkHyperlinkClass->get_start_index = my_atk_hyperlink_get_start_index;
+    atkHyperlinkClass->get_end_index = my_atk_hyperlink_get_end_index;
+    atkHyperlinkClass->is_valid = my_atk_hyperlink_is_valid;
+    atkHyperlinkClass->link_state = my_atk_hyperlink_link_state;
+    atkHyperlinkClass->get_n_anchors = my_atk_hyperlink_get_n_anchors;
+    atkHyperlinkClass->is_selected_link = my_atk_hyperlink_is_selected_link; 
+}
+
+GType my_atk_hyperlink_get_type()
+{
+    static GType type = 0;
+    if(type == 0)
+    {
+        static const GTypeInfo typeInfo = 
+        {
+            sizeof(MyAtkHyperlinkClass),
+            NULL,                       //base_init
+            NULL,                       //base_finalize
+            my_atk_hyperlink_class_init,     //class_init
+            NULL,                       //class_finalize
+            NULL,                       //class_data
+            sizeof(MyAtkHyperlink),
+            0,                          //n_preallocs
+            my_atk_hyperlink_instance_init   //instance_init
+        };
+        type = g_type_register_static(ATK_TYPE_HYPERLINK, "MyAtkHyperlink", &typeInfo, 0);
+    }
+    return type;    
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-hyperlink.h pyatspi2/tests/dummyatk/my-atk-hyperlink.h
--- pyatspi2.old/tests/dummyatk/my-atk-hyperlink.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-hyperlink.h	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MY_ATK_HYPERLINK_H
+#define MY_ATK_HYPERLINK_H
+/*
+ * MyAtkHyperlink: implements AtkHyperlink
+ */
+#include <atk/atk.h>
+
+#define MY_TYPE_ATK_HYPERLINK             (my_atk_hyperlink_get_type ())
+#define MY_ATK_HYPERLINK(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_ATK_HYPERLINK, MyAtkHyperlink))
+#define MY_ATK_HYPERLINK_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MY_TYPE_ATK_HYPERLINK, MyAtkHyperlinkClass))
+#define MY_IS_ATK_HYPERLINK(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_ATK_HYPERLINK))
+#define MY_IS_ATK_HYPERLINK_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MY_TYPE_ATK_HYPERLINK))
+#define MY_ATK_HYPERLINK_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MY_TYPE_ATK_HYPERLINK, MyAtkHyperlinkClass))
+
+typedef struct _MyAtkHyperlink MyAtkHyperlink;
+typedef struct _MyAtkHyperlinkClass MyAtkHyperlinkClass;
+
+struct _MyAtkHyperlink
+{
+    AtkHyperlink parent;
+    
+    gint start_index, end_index;
+    
+    gchar* uri;
+    gint number_of_anchors;//0 on "clear" hyperlink and 1 after set it
+    gboolean is_selected;
+};
+
+struct _MyAtkHyperlinkClass
+{
+    AtkHyperlinkClass parent;
+};
+
+GType my_atk_hyperlink_get_type();
+#endif /*MY_ATK_HYPERLINK_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-hypertext.c pyatspi2/tests/dummyatk/my-atk-hypertext.c
--- pyatspi2.old/tests/dummyatk/my-atk-hypertext.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-hypertext.c	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <atk/atk.h>
+
+#include "my-atk-text.h"
+#include "my-atk-hyperlink.h"
+#include "my-atk-hypertext.h"
+
+//***************************implementation****************************************
+static MyAtkTextClass *parent_class_atk_text = NULL;
+
+typedef struct
+{
+    gint start_offset, end_offset;
+    gint index;
+}HyperlinkRange;
+// Implementation of virtual functions
+
+//***************************my_atk_hypertext_get_n_links*************************
+gint my_atk_hypertext_get_n_links(AtkHypertext* hypertext)
+{
+    MyAtkHypertext* self = (MyAtkHypertext*)hypertext;
+    
+    return self->hyperlinks->len; 
+}
+//***************************my_atk_hypertext_get_link***********************
+AtkHyperlink* my_atk_hypertext_get_link(AtkHypertext* hypertext, gint link_index)
+{
+    MyAtkHypertext* self = (MyAtkHypertext*)hypertext;
+    
+    if(link_index < 0 || link_index >= self->hyperlinks->len)
+        return NULL;
+    return g_ptr_array_index(self->hyperlinks, link_index);
+}
+//*************************my_atk_hypertext_get_link_index*******************
+gint my_atk_hypertext_get_link_index(AtkHypertext* hypertext, gint char_index)
+{
+    gint i;
+    MyAtkHypertext* self = (MyAtkHypertext*)hypertext;
+    GArray* ranges = self->hyperlink_ranges; 
+    for(i = ranges->len - 1; i >= 0; i--)
+    {
+        HyperlinkRange *range = &g_array_index(ranges, HyperlinkRange, i);
+        if(range->start_offset <= char_index)
+        {
+            if(range->end_offset > char_index)return range->index;
+            break;
+        }
+    }
+    return -1;
+}
+//others functions
+gboolean my_atk_hypertext_add_hyperlink(MyAtkHypertext* hypertext,
+    gint start_index, gint end_index, const gchar* uri)
+{
+    MyAtkHyperlink* new_hyperlink;
+    GArray* ranges = hypertext->hyperlink_ranges;
+    gint i;
+    for(i = 0; i < ranges->len; i++)
+    {
+        HyperlinkRange *range = &g_array_index(ranges, HyperlinkRange, i);
+        if(range->end_offset <= start_index) continue;
+        if(range->start_offset < end_index) return FALSE;
+        break;
+    }
+    new_hyperlink = my_atk_hyperlink_new(start_index, end_index, uri);
+    g_ptr_array_add(hypertext->hyperlinks, new_hyperlink);
+    HyperlinkRange new_range;
+    new_range.start_offset = start_index;
+    new_range.end_offset = end_index;
+    new_range.index = hypertext->hyperlinks->len - 1;
+    g_array_insert_val(ranges, i, new_range);
+    return TRUE;
+}
+//
+void my_atk_hypertext_select_link(MyAtkHypertext* hypertext, gint index)
+{
+    if(index < 0 || index >= my_atk_hypertext_get_n_links((AtkHypertext*)hypertext))
+        return;
+    
+    if(hypertext->current_selected_link != -1)
+    {
+        MyAtkHyperlink *selected_link_old = 
+            (MyAtkHyperlink*)my_atk_hypertext_get_link(
+            (AtkHypertext*)hypertext, hypertext->current_selected_link);
+        selected_link_old->is_selected = FALSE;
+    }
+    
+    hypertext->current_selected_link = index;
+    MyAtkHyperlink *selected_link_new = (MyAtkHyperlink*)my_atk_hypertext_get_link(
+        (AtkHypertext*)hypertext, hypertext->current_selected_link);
+    selected_link_new->is_selected = TRUE;
+    
+    g_signal_emit_by_name(hypertext,
+        "link-selected", hypertext->current_selected_link);    
+}
+//initialize/finalize functions
+static void my_atk_hypertext_instance_init(GTypeInstance *obj, gpointer g_class)
+{
+    MyAtkHypertext *self = (MyAtkHypertext*)obj;
+    
+    self->hyperlink_ranges = g_array_new(FALSE, FALSE, sizeof(HyperlinkRange));
+    self->hyperlinks = g_ptr_array_new();
+    
+    self->current_selected_link = -1;
+}
+static void my_atk_hypertext_instance_finalize(GObject* obj)
+{
+    MyAtkHypertext *self = (MyAtkHypertext*)obj;
+    
+    g_array_free(self->hyperlink_ranges, FALSE);
+    
+    g_ptr_array_foreach(self->hyperlinks,(GFunc)g_object_unref, NULL);
+    g_ptr_array_free(self->hyperlinks, FALSE);
+}
+
+static void my_atk_hypertext_class_init(gpointer g_class, gpointer class_data)
+{
+    GObjectClass* g_object_class = (GObjectClass*)g_class;
+    //GObject virtual table
+    g_object_class->finalize = my_atk_hypertext_instance_finalize;
+    //parent_class
+    parent_class_atk_text = g_type_class_peek_parent(g_class);
+}
+static void my_atk_hypertext_interface_init(gpointer g_iface, gpointer iface_data)
+{
+    AtkHypertextIface *klass = (AtkHypertextIface*)g_iface;
+    
+    klass->get_link = my_atk_hypertext_get_link;
+    klass->get_n_links = my_atk_hypertext_get_n_links;
+    klass->get_link_index = my_atk_hypertext_get_link_index;
+}
+
+GType my_atk_hypertext_get_type()
+{
+    static GType type = 0;
+    if(type == 0)
+    {
+        static const GTypeInfo typeInfo = 
+        {
+            sizeof(MyAtkHypertextClass),
+            NULL,                       //base_init
+            NULL,                       //base_finalize
+            my_atk_hypertext_class_init,     //class_init
+            NULL,                       //class_finalize
+            NULL,                       //class_data
+            sizeof(MyAtkHypertext),
+            0,                          //n_preallocs
+            my_atk_hypertext_instance_init   //instance_init
+        };
+
+        static const GInterfaceInfo AtkTextIface_info = 
+        {
+            my_atk_text_interface_init,         /* interface_init*/
+            NULL,                               /* interface_finalize*/
+            NULL                                /* interface_data */
+        };
+        static const GInterfaceInfo AtkHypertextIface_info = 
+        {
+            my_atk_hypertext_interface_init,/* interface_init*/
+            NULL,                               /* interface_finalize*/
+            NULL                                /* interface_data */
+        };
+        type = g_type_register_static(MY_TYPE_ATK_TEXT, "MyAtkHypertext", &typeInfo, 0);
+        g_type_add_interface_static(type,
+            ATK_TYPE_TEXT,
+            &AtkTextIface_info);
+        
+        g_type_add_interface_static(type,
+            ATK_TYPE_HYPERTEXT,
+            &AtkHypertextIface_info);
+    }
+    return type;    
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-hypertext.h pyatspi2/tests/dummyatk/my-atk-hypertext.h
--- pyatspi2.old/tests/dummyatk/my-atk-hypertext.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-hypertext.h	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MY_ATK_HYPERTEXT_H
+#define MY_ATK_HYPERTEXT_H
+/*
+ * MyAtkHypertext: implements AtkHypertext
+ */
+#include <atk/atk.h>
+#include <my-atk-text.h>
+
+#define MY_TYPE_ATK_HYPERTEXT             (my_atk_hypertext_get_type ())
+#define MY_ATK_HYPERTEXT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_ATK_HYPERTEXT, MyAtkHypertext))
+#define MY_ATK_HYPERTEXT_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MY_TYPE_ATK_HYPERTEXT, MyAtkHypertextClass))
+#define MY_IS_ATK_HYPERTEXT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_ATK_HYPERTEXT))
+#define MY_IS_ATK_HYPERTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MY_TYPE_ATK_HYPERTEXT))
+#define MY_ATK_HYPERTEXT_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MY_TYPE_ATK_HYPERTEXT, MyAtkHypertextClass))
+
+typedef struct _MyAtkHypertext MyAtkHypertext;
+typedef struct _MyAtkHypertextClass MyAtkHypertextClass;
+
+struct _MyAtkHypertext
+{
+    MyAtkText parent;
+    
+    GArray* hyperlink_ranges;
+    GPtrArray* hyperlinks;
+    
+    gint current_selected_link;
+};
+
+struct _MyAtkHypertextClass
+{
+    MyAtkTextClass parent;
+};
+#endif /*MY_ATK_HYPERTEXT_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-object.c pyatspi2/tests/dummyatk/my-atk-object.c
--- pyatspi2.old/tests/dummyatk/my-atk-object.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-object.c	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#include <stdio.h>
+#include <atk/atk.h>
+
+#include "my-atk-object.h"
+
+static AtkObjectClass *atk_object_parent_class = NULL;
+
+void my_atk_object_add_child(MyAtkObject* parent, MyAtkObject* child)
+{
+    g_ptr_array_add(parent->children, child);
+    g_object_ref_sink(child);
+
+    atk_object_set_parent(ATK_OBJECT(child), ATK_OBJECT(parent));
+    
+    g_signal_emit_by_name(parent, "children-changed::add",
+        parent->children->len - 1, child);
+}
+
+void my_atk_object_remove_child(MyAtkObject* parent, MyAtkObject* child)
+{
+    gint i;
+    for(i = parent->children->len - 1; i >= 0; i--)
+    {
+        if(g_ptr_array_index(parent->children, i) == child) break;
+    }
+    if(i < 0)return;
+
+    g_ptr_array_remove_index(parent->children, i);
+    g_object_unref(child);
+    g_signal_emit_by_name(parent, "children-changed::remove",
+        i, child);
+}
+
+static void my_atk_object_set_parent(AtkObject *accessible, AtkObject *parent)
+{
+    g_return_if_fail(parent != NULL);
+
+    MyAtkObject *self = MY_ATK_OBJECT(accessible);
+    AtkObject *parent_old = (atk_object_get_parent(accessible));
+    
+    if(parent_old == parent)
+    {
+        //nothing to do because parent does not change
+        return;
+    }
+    
+    //set field 'parent' in child using 'base-method'
+    atk_object_parent_class->set_parent(accessible, parent);
+    
+    if(parent_old != NULL)
+    {
+        my_atk_object_remove_child((MyAtkObject*)parent_old, self);
+    }
+}
+
+static gint my_atk_object_get_n_children(AtkObject *accessible)
+{
+    return MY_ATK_OBJECT(accessible)->children->len;
+}
+
+static AtkObject* my_atk_object_ref_child(AtkObject *accessible, gint i)
+{
+    MyAtkObject *self = MY_ATK_OBJECT(accessible); 
+    if(i < 0 || i >= self->children->len)
+    {
+        printf("ref_child: Incorrect index of child.\n");
+        return NULL;
+    }
+
+    AtkObject* child = (AtkObject*)
+        g_ptr_array_index(self->children, i);
+
+    return (child == NULL) ? NULL : g_object_ref(child);
+}
+
+static gint my_atk_object_get_index_in_parent(AtkObject *accessible)
+{
+    AtkObject *parent = atk_object_get_parent(accessible);
+    if(parent == NULL) return -1;//no parent
+    
+    MyAtkObject *parent_my = MY_ATK_OBJECT(parent);
+
+    int i = parent_my->children->len;
+    for(; i>=0; i--)
+    {
+        if(g_ptr_array_index(parent_my->children,i) == accessible)
+            break;
+    }
+    if(i < 0)printf("Something wrong in parent-child strucutre.\n");
+    return i;//if error, i will be equal to -1
+}
+
+static AtkStateSet *my_atk_object_ref_state_set(AtkObject *accessible)
+{
+    MyAtkObject *obj = MY_ATK_OBJECT(accessible);
+
+    if (obj->state_set == NULL)
+        obj->state_set = atk_state_set_new();
+    return g_object_ref(G_OBJECT(obj->state_set));
+}
+
+static AtkAttributeSet *my_atk_object_get_attributes (AtkObject *accessible)
+{
+    MyAtkObject *obj = MY_ATK_OBJECT(accessible);
+    AtkAttributeSet *rs = obj->attributes = NULL;
+    AtkAttribute *a, *b, *c;
+
+    a = g_new(AtkAttribute, 1);
+    b = g_new(AtkAttribute, 1);
+    c = g_new(AtkAttribute, 1);
+
+    a->name = g_strdup("foo");
+    a->value = g_strdup("bar");
+    b->name = g_strdup("baz");
+    b->value = g_strdup("qux");
+    c->name = g_strdup("quux");
+    c->value = g_strdup("corge");
+
+    rs = g_slist_append(rs, (gpointer) a); 
+    rs = g_slist_append(rs, (gpointer) b); 
+    rs = g_slist_append(rs, (gpointer) c); 
+}
+
+//function, needed in instance_finalize()
+static void my_unref1(gpointer data, gpointer user_data)
+{
+    g_object_unref(data);
+}
+
+static void my_atk_object_instance_finalize(GObject *obj)
+{
+    MyAtkObject *self = (MyAtkObject*) obj;
+    //unrefs all children
+    g_ptr_array_foreach(self->children, my_unref1, NULL);
+    //then free array (without frees pointers)
+    g_ptr_array_free(self->children, FALSE);
+    //chain to parent class
+    G_OBJECT_CLASS(atk_object_parent_class)->finalize(obj);
+}
+
+void my_atk_object_class_init(gpointer g_class, gpointer g_class_data)
+{
+    AtkObjectClass *atkObjectClass = (AtkObjectClass*)g_class;
+    
+    ((GObjectClass*)g_class)->finalize = my_atk_object_instance_finalize;
+    //set pointers to new functions in table of virtuals functions
+    atkObjectClass->set_parent = my_atk_object_set_parent;
+    atkObjectClass->get_n_children = my_atk_object_get_n_children;
+    atkObjectClass->ref_child = my_atk_object_ref_child;
+    atkObjectClass->get_index_in_parent = my_atk_object_get_index_in_parent;
+    atkObjectClass->ref_state_set = my_atk_object_ref_state_set;
+    atkObjectClass->get_attributes = my_atk_object_get_attributes;
+
+    atk_object_parent_class = g_type_class_peek_parent(g_class);
+}
+
+static void my_atk_object_instance_init(GTypeInstance *obj, gpointer g_class)
+{
+    MyAtkObject *self = (MyAtkObject*)obj;
+
+    self->children = g_ptr_array_sized_new(10);
+    self->attributes =  g_slist_alloc();
+}
+
+GType my_atk_object_get_type()
+{
+    static GType type = 0;
+    if(type == 0)
+    {
+        static const GTypeInfo typeInfo = 
+        {
+            sizeof(MyAtkObjectClass),
+            NULL, //base_init
+            NULL, //base_finalize
+            my_atk_object_class_init, //class_init
+            NULL, //class_finalize
+            NULL, //class_data
+            sizeof(MyAtkObject),
+            0, //n_preallocs
+            my_atk_object_instance_init //instance_init
+        };
+        type = g_type_register_static(ATK_TYPE_OBJECT,"MyAtkObject",&typeInfo,0);
+    }
+    return type;
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-object.h pyatspi2/tests/dummyatk/my-atk-object.h
--- pyatspi2.old/tests/dummyatk/my-atk-object.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-object.h	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MY_ATK_OBJECT_H
+#define MY_ATK_OBJECT_H
+
+#include <atk/atk.h>
+
+#define MY_TYPE_ATK_OBJECT             (my_atk_object_get_type ())
+#define MY_ATK_OBJECT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_ATK_OBJECT, MyAtkObject))
+#define MY_ATK_OBJECT_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MY_TYPE_ATK_OBJECT, MyAtkObjectClass))
+#define MY_IS_ATK_OBJECT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_ATK_OBJECT))
+#define MY_IS_ATK_OBJECT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MY_TYPE_ATK_OBJECT))
+#define MY_ATK_OBJECT_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MY_TYPE_ATK_OBJECT, MyAtkObjectClass))
+
+typedef struct _MyAtkObject MyAtkObject;
+typedef struct _MyAtkObjectClass MyAtkObjectClass;
+
+struct _MyAtkObject
+{
+    AtkObject parent;
+    //array of children
+    AtkStateSet *state_set;
+    AtkAttributeSet *attributes;
+    GPtrArray* children;
+    gint id;
+};
+
+struct _MyAtkObjectClass
+{
+    AtkObjectClass parent;
+};
+
+GType my_atk_object_get_type();
+
+void my_atk_object_add_child(MyAtkObject* parent, MyAtkObject* child);
+
+void my_atk_object_remove_child(MyAtkObject* parent, MyAtkObject* child);
+
+#endif /*MY_ATK_OBJECT_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-selection.c pyatspi2/tests/dummyatk/my-atk-selection.c
--- pyatspi2.old/tests/dummyatk/my-atk-selection.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-selection.c	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,351 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* This file contains both declaration and definition of the MyAtkSelection,
+ * a GObject that implements the AtkSelectionIface interface.
+ */
+
+#include <glib-object.h>
+#include <atk/atk.h> 
+
+#include "my-atk-object.h"
+#include "my-atk-selection.h"
+
+/******************************************************************/
+/*                    Implementation                              */
+/******************************************************************/
+static GObjectClass *parent_class_simple_selection = NULL;
+
+/* Implementation of the AtkSelectionIface interface. */
+static gboolean
+simple_selection_add_selection (AtkSelection *selection, gint i)
+{
+    MyAtkSelection* self = (MyAtkSelection*)selection;
+    if ((!self) || self->disposed)
+    {
+        return FALSE;
+    }
+    
+    if ((i >= 0) && (i < TEST_SELECTION_NCHILDREN))
+    {
+        /* If the child is not selected, select it and send the signal */
+        if (!self->is_selected[i])
+        {
+            self->is_selected[i] = TRUE;
+            g_signal_emit_by_name ((gpointer)self, "selection-changed");
+        }
+                
+        return TRUE;    
+    }
+    else
+    {
+        return FALSE;
+    }    
+    
+}
+
+static gboolean 
+simple_selection_clear_selection (AtkSelection *selection)
+{
+    MyAtkSelection* self = (MyAtkSelection*)selection;
+    if ((!self) || self->disposed)
+    {
+        return FALSE;
+    }
+    
+    /* clear selection */
+    {
+        gboolean changed = FALSE;
+        int i;
+        for (i = 0; i < TEST_SELECTION_NCHILDREN; ++i)
+        {
+            changed |= self->is_selected[i];
+            self->is_selected[i] = FALSE;
+        }
+        
+        if (changed)
+        {
+            g_signal_emit_by_name ((gpointer)self, "selection-changed");
+        }
+    }
+    
+    return TRUE;
+}
+
+static AtkObject* 
+simple_selection_ref_selection (AtkSelection *selection, gint i)
+{
+    int pos;
+    int nsel;
+    MyAtkSelection* self = (MyAtkSelection*)selection;
+    if ((!self) || self->disposed)
+    {
+        return NULL;
+    }
+    
+    nsel = 0;
+    for (pos = 0; pos < TEST_SELECTION_NCHILDREN; ++pos)
+    {
+        if (self->is_selected[pos])
+        {
+            if (i == nsel)
+            {
+                g_object_ref (G_OBJECT (self->child[pos]));
+                return ATK_OBJECT(self->child[pos]);
+            }
+            ++nsel;
+        }
+    }
+            
+    return NULL;
+}
+
+static gint 
+simple_selection_get_selection_count (AtkSelection *selection)
+{
+    MyAtkSelection* self = (MyAtkSelection*)selection;
+    
+    int cnt = 0;
+    int i;
+    
+    if ((!self) || self->disposed)
+    {
+        return 0;
+    }
+    
+    for (i = 0; i < TEST_SELECTION_NCHILDREN; ++i)
+    {
+        if (self->is_selected[i]) 
+        {
+            ++cnt;
+        }
+    }
+    
+     return cnt;
+}
+
+static gboolean 
+simple_selection_is_child_selected (AtkSelection *selection, gint i)
+{
+    MyAtkSelection* self = (MyAtkSelection*)selection;
+    if ((!self) || self->disposed)
+    {
+        return FALSE;
+    }
+    
+    if ((i >= 0) && (i < TEST_SELECTION_NCHILDREN))
+    {
+        return (self->is_selected[i]);
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+
+static gboolean 
+simple_selection_remove_selection (AtkSelection *selection, gint i)
+{
+    int pos;
+    int nsel;
+    
+    MyAtkSelection* self = (MyAtkSelection*)selection;
+    if ((!self) || self->disposed)
+    {
+        return FALSE;
+    }
+    
+    nsel = 0;
+    for (pos = 0; pos < TEST_SELECTION_NCHILDREN; ++pos)
+    {
+        if (self->is_selected[pos])
+        {
+            if (i == nsel)
+            {
+                self->is_selected[pos] = FALSE;
+                g_signal_emit_by_name ((gpointer)self, "selection-changed");
+                return TRUE;
+            }
+            ++nsel;
+        }
+    }
+    
+    return TRUE;
+}
+
+static gboolean 
+simple_selection_select_all_selection (AtkSelection *selection)
+{
+    MyAtkSelection* self = (MyAtkSelection*)selection;
+    if ((!self) || self->disposed)
+    {
+        return FALSE;
+    }
+    
+    if (!self->multisel_supported)
+    {
+        return FALSE;
+    }
+    
+    /* select all */
+    {
+        gboolean changed = FALSE;
+        int i;
+        for (i = 0; i < TEST_SELECTION_NCHILDREN; ++i)
+        {
+            changed |= !self->is_selected[i];
+            self->is_selected[i] = TRUE;
+        }
+        
+        if (changed)
+        {
+            g_signal_emit_by_name ((gpointer)self, "selection-changed");
+        }
+    }
+    
+    return TRUE;
+}
+
+/******************************************************************/
+static void
+simple_selection_interface_init (gpointer g_iface, gpointer iface_data)
+{
+    AtkSelectionIface *klass = (AtkSelectionIface *)g_iface;
+    
+    /* set up overrides here */
+    klass->add_selection = 
+        (gboolean (*) (AtkSelection *selection, gint i)) simple_selection_add_selection;
+    
+    klass->clear_selection = 
+        (gboolean (*) (AtkSelection *selection)) simple_selection_clear_selection;
+    
+    klass->ref_selection = 
+        (AtkObject* (*) (AtkSelection *selection, gint i)) simple_selection_ref_selection;
+    
+    klass->get_selection_count = 
+        (gint (*) (AtkSelection *selection)) simple_selection_get_selection_count;
+    
+    klass->is_child_selected = 
+        (gboolean (*) (AtkSelection *selection, gint i)) simple_selection_is_child_selected;
+    
+    klass->remove_selection = 
+        (gboolean (*) (AtkSelection *selection, gint i)) simple_selection_remove_selection;
+    
+    klass->select_all_selection = 
+        (gboolean (*) (AtkSelection *selection)) simple_selection_select_all_selection;
+}
+
+static void
+simple_selection_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+    MyAtkSelection *self = (MyAtkSelection *)instance;
+    int i;
+    
+    self->disposed = FALSE;
+    self->multisel_supported = TRUE;
+    for (i = 0; i < TEST_SELECTION_NCHILDREN; ++i)
+    {
+        self->child[i] = MY_ATK_OBJECT (g_object_new (MY_TYPE_ATK_OBJECT, NULL));
+        self->child[i]->id = i;
+        self->is_selected[i] = FALSE; /* not selected by default */
+    }
+}
+
+static void
+my_atk_selection_dispose (GObject *obj)
+{
+    MyAtkSelection *self = (MyAtkSelection *)obj;
+    int i;
+
+    if (self->disposed) 
+    {
+        return;
+    }
+    
+    /* Make sure dispose does not run twice. */
+    self->disposed = TRUE;
+
+    for (i = 0; i < TEST_SELECTION_NCHILDREN; ++i)
+    {
+        g_object_unref (G_OBJECT (self->child[i]));
+    }
+
+    /* Chain up to the parent class */
+    G_OBJECT_CLASS (parent_class_simple_selection)->dispose (obj);
+}
+
+static void
+my_atk_selection_finalize (GObject *obj)
+{
+    /*MyAtkSelection *self = (MyAtkSelection *)obj;
+    if (self)
+    {
+    }*/
+    
+    /* Chain up to the parent class */
+    G_OBJECT_CLASS (parent_class_simple_selection)->finalize (obj);
+}
+
+static void
+my_atk_selection_class_init (gpointer g_class, gpointer g_class_data)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
+    MyAtkSelectionClass *klass = MY_ATK_SELECTION_CLASS (g_class);
+
+    gobject_class->dispose = my_atk_selection_dispose;
+    gobject_class->finalize = my_atk_selection_finalize;
+
+    parent_class_simple_selection = g_type_class_peek_parent (klass);
+}
+
+GType 
+my_atk_selection_get_type (void)
+{
+    static GType type = 0;
+    if (type == 0) 
+    {
+        static const GTypeInfo info = 
+        {
+            sizeof (MyAtkSelectionClass),
+            NULL,   /* base_init */
+            NULL,   /* base_finalize */
+            my_atk_selection_class_init, /* class_init */
+            NULL,   /* class_finalize */
+            NULL,   /* class_data */
+            sizeof (MyAtkSelection),
+            0,      /* n_preallocs */
+            simple_selection_instance_init    /* instance_init */
+        };
+                
+        static const GInterfaceInfo iface_info = 
+        {
+            (GInterfaceInitFunc) simple_selection_interface_init,    /* interface_init */
+            NULL,                                       /* interface_finalize */
+            NULL                                        /* interface_data */
+        };
+        type = g_type_register_static (MY_TYPE_ATK_OBJECT,
+                                       "MyAtkSelectionType",
+                                       &info, 0);
+        g_type_add_interface_static (type,
+                                     ATK_TYPE_SELECTION,
+                                     &iface_info);
+    }
+    return type;
+}
+
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-selection.h pyatspi2/tests/dummyatk/my-atk-selection.h
--- pyatspi2.old/tests/dummyatk/my-atk-selection.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-selection.h	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* This file contains both declaration and definition of the MyAtkSelection,
+ * a GObject that implements the AtkSelectionIface interface.
+ */
+
+#ifndef MY_ATK_SELECTION_H
+#define MY_ATK_SELECTION_H
+
+#include <glib-object.h>
+#include <atk/atk.h> 
+
+#include <my-atk-object.h>
+
+#define MY_TYPE_ATK_SELECTION             (my_atk_selection_get_type ())
+#define MY_ATK_SELECTION(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_ATK_SELECTION, MyAtkSelection))
+#define MY_ATK_SELECTION_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MY_TYPE_ATK_SELECTION, MyAtkSelectionClass))
+#define MY_IS_ATK_SELECTION(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_ATK_SELECTION))
+#define MY_IS_ATK_SELECTION_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MY_TYPE_ATK_SELECTION))
+#define MY_ATK_SELECTION_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MY_TYPE_ATK_SELECTION, MyAtkSelectionClass))
+
+/* Number of child objects for the MyAtkSelection instance */
+#define TEST_SELECTION_NCHILDREN 10    
+
+typedef struct _MyAtkSelection MyAtkSelection;
+typedef struct _MyAtkSelectionClass MyAtkSelectionClass;
+
+struct _MyAtkSelection 
+{
+    MyAtkObject parent;
+        
+    gboolean disposed;
+    
+    /* TRUE if multiple selection is supported, FALSE otherwise.
+     * default - TRUE.
+     */
+    gboolean multisel_supported;
+    
+    /* Children of this object */
+    MyAtkObject* child[TEST_SELECTION_NCHILDREN];
+    
+    /* is_selected[i] == TRUE means the ith child is selected, == FALSE - 
+     * it is not.
+     */
+    gboolean is_selected[TEST_SELECTION_NCHILDREN];
+};
+
+struct _MyAtkSelectionClass 
+{
+    MyAtkObjectClass parent;
+};
+
+GType 
+my_atk_selection_get_type (void);
+
+#endif /*MY_ATK_SELECTION_H*/
+
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-streamable-content.c pyatspi2/tests/dummyatk/my-atk-streamable-content.c
--- pyatspi2.old/tests/dummyatk/my-atk-streamable-content.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-streamable-content.c	2019-08-27 19:10:03.873588522 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <atk/atk.h>
+
+#include "my-atk-object.h"
+#include "my-atk-streamable-content.h"
+
+//*************************implementation***********************
+//implementation of virtual functions
+//*****************get_n_mime_types************
+static gint my_atk_streamable_content_get_n_mime_types(
+    AtkStreamableContent *streamable)
+{
+    g_return_val_if_fail(MY_IS_ATK_STREAMABLE_CONTENT(streamable), 0);
+    
+    return sizeof(mime_types) / sizeof(mime_types[0]);
+}
+//*****************get_mime_type****************
+static const gchar* my_atk_streamable_content_get_mime_type(
+    AtkStreamableContent *streamable,
+    gint i)
+{
+    g_return_val_if_fail(MY_IS_ATK_STREAMABLE_CONTENT(streamable), NULL);
+    
+    if((i < 0) || (i >= sizeof(mime_types) / sizeof(mime_types[0])))
+    {
+        return NULL;
+    }
+    return mime_types[i];
+}
+//**********************get_stream*******************
+static GIOChannel* my_atk_streamable_content_get_stream(
+    AtkStreamableContent *streamable,
+    const gchar* mime_type)
+{
+    gint i;
+    g_return_val_if_fail(MY_IS_ATK_STREAMABLE_CONTENT(streamable), NULL);
+    
+    for(i = 0; i < sizeof(mime_types) / sizeof(mime_types[0]); i++)
+    {
+        if(strcmp(mime_type, mime_types[i]) == 0)
+        {
+            GError *error = NULL;
+            gchar* full_filename = T2C_GET_DATA_PATH(file_names[i]);
+            GIOChannel* channel = g_io_channel_new_file(full_filename, "r", &error);
+            if(error != NULL)
+            {
+                TRACE("Cannot open file '%s' for read: %s", full_filename,
+                    error->message);
+                g_error_free(error);
+            }
+            g_free(full_filename);
+            return channel;
+        }
+    }
+    return NULL;
+}
+//others functions
+static void my_atk_streamable_content_interface_init(gpointer g_iface, gpointer iface_data)
+{
+    AtkStreamableContentIface *klass = (AtkStreamableContentIface*)g_iface;
+    
+    klass->get_n_mime_types = my_atk_streamable_content_get_n_mime_types;
+    klass->get_mime_type = my_atk_streamable_content_get_mime_type;
+    klass->get_stream = my_atk_streamable_content_get_stream;
+}
+
+GType my_atk_streamable_content_get_type()
+{
+    static GType type = 0;
+    if(type == 0)
+    {
+        static const GTypeInfo typeInfo = 
+        {
+            sizeof(MyAtkStreamableContentClass),
+            NULL, //base_init
+            NULL, //base_finalize
+            NULL, //class_init
+            NULL, //class_finalize
+            NULL, //class_data
+            sizeof(MyAtkStreamableContent),
+            0, //n_preallocs
+            NULL //instance_init
+        };
+
+        static const GInterfaceInfo iface_info = 
+        {
+            my_atk_streamable_content_interface_init,    /* interface_init*/
+            NULL,                               /* interface_finalize*/
+            NULL                                /* interface_data */
+        };
+        type = g_type_register_static(MY_TYPE_ATK_OBJECT, "MyAtkStreamableContent", &typeInfo, 0);
+        g_type_add_interface_static(type,
+            ATK_TYPE_STREAMABLE_CONTENT,
+            &iface_info);
+    }
+    return type;    
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-streamable-content.h pyatspi2/tests/dummyatk/my-atk-streamable-content.h
--- pyatspi2.old/tests/dummyatk/my-atk-streamable-content.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-streamable-content.h	2019-08-27 19:10:03.877588542 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MY_ATK_STREAMABLE_CONTENT_H
+#define MY_ATK_STREAMABLE_CONTENT_H
+
+/*
+ * MyAtkStreamableContent: derives GObject and implements AtkStreamableContent
+ */
+
+#include <atk/atk.h>
+
+#include "my-atk-object.h"
+
+#define MY_TYPE_ATK_STREAMABLE_CONTENT             (my_atk_streamable_content_get_type ())
+#define MY_ATK_STREAMABLE_CONTENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_ATK_STREAMABLE_CONTENT, MyAtkStreamableContent))
+#define MY_ATK_STREAMABLE_CONTENT_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MY_TYPE_ATK_STREAMABLE_CONTENT, MyAtkStreamableContentClass))
+#define MY_IS_ATK_STREAMABLE_CONTENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_ATK_STREAMABLE_CONTENT))
+#define MY_IS_ATK_STREAMABLE_CONTENT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MY_TYPE_ATK_STREAMABLE_CONTENT))
+#define MY_ATK_STREAMABLE_CONTENT_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MY_TYPE_ATK_STREAMABLE_CONTENT, MyAtkStreamableContentClass))
+
+typedef struct _MyAtkStreamableContent MyAtkStreamableContent;
+typedef struct _MyAtkStreamableContentClass MyAtkStreamableContentClass;
+
+static const gchar* mime_types[]={"text/plain", "text/richtext"};
+static const gchar* file_names[]={"file1", "file2"};
+struct _MyAtkStreamableContent
+{
+    MyAtkObject parent;
+};
+
+struct _MyAtkStreamableContentClass
+{
+    MyAtkObjectClass parent;
+};
+
+GType my_atk_streamable_content_get_type();
+#endif /*MY_ATK_STREAMABLE_CONTENT_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-table.c pyatspi2/tests/dummyatk/my-atk-table.c
--- pyatspi2.old/tests/dummyatk/my-atk-table.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-table.c	2019-08-27 19:10:03.877588542 +0200
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* This file contains both declaration and definition of the MyAtkTable,
+ * a GObject that pretends to implement the AtkTableIface interface (it 
+ * registers appropriate interface), but provides no implementation for any of the
+ * methods of this interface (NULL-filled vftbl).
+ */
+
+#include <glib-object.h>
+#include <atk/atk.h> 
+
+#include "my-atk-object.h"
+#include "my-atk-table.h"
+    
+///////////////////////////////////////////////////////////////////////////
+// Helper functions and data
+///////////////////////////////////////////////////////////////////////////
+void
+my_atk_table_select_rows (MyAtkTable* table, gboolean sel_scheme[])
+{
+    // the function does nothing  
+}
+
+void
+my_atk_table_select_columns (MyAtkTable* table, gboolean sel_scheme[])
+{
+    // the function does nothing
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Implementation
+///////////////////////////////////////////////////////////////////////////
+static GObjectClass *parent_class_table = NULL;
+
+/******************************************************************/
+static void
+table_interface_init (gpointer g_iface, gpointer iface_data)
+{
+    AtkTableIface *klass = (AtkTableIface *)g_iface;
+    
+    /* set up overrides here */
+    klass-> ref_at =
+        (AtkObject* (*) (AtkTable *table, gint row, gint column)) NULL;
+    klass-> get_index_at =
+        (gint (*) (AtkTable *table, gint row, gint column)) NULL;
+    klass-> get_column_at_index =
+        (gint (*) (AtkTable *table, gint index_)) NULL;
+    klass-> get_row_at_index =
+        (gint (*) (AtkTable *table, gint index_)) NULL;
+    klass-> get_n_columns =
+        (gint (*) (AtkTable *table)) NULL;
+    klass-> get_n_rows =
+        (gint (*) (AtkTable *table)) NULL;
+    klass-> get_column_extent_at =
+        (gint (*) (AtkTable *table, gint row, gint column)) NULL;
+    klass-> get_row_extent_at =
+        (gint (*) (AtkTable *table, gint row, gint column)) NULL;
+    klass-> get_caption =
+        (AtkObject* (*) (AtkTable *table)) NULL;
+    klass-> get_column_description =
+        (const gchar* (*) (AtkTable *table, gint column)) NULL;
+    klass-> get_column_header =
+        (AtkObject* (*) (AtkTable *table, gint column)) NULL;
+    klass-> get_row_description =
+        (const gchar* (*) (AtkTable *table, gint row)) NULL;
+    klass-> get_row_header =
+        (AtkObject* (*) (AtkTable *table, gint row)) NULL;
+    klass-> get_summary =
+        (AtkObject* (*) (AtkTable *table)) NULL;
+    klass-> set_caption =
+        (void (*) (AtkTable *table, AtkObject *caption)) NULL;
+    klass-> set_column_description =
+        (void (*) (AtkTable *table, gint column, const gchar *description)) NULL;
+    klass-> set_column_header =
+        (void (*) (AtkTable *table, gint column, AtkObject *header)) NULL;
+    klass-> set_row_description =
+        (void (*) (AtkTable *table, gint row, const gchar *description)) NULL;
+    klass-> set_row_header =
+        (void (*) (AtkTable *table, gint row, AtkObject *header)) NULL;
+    klass-> set_summary =
+        (void (*) (AtkTable *table, AtkObject *accessible)) NULL;
+    klass-> get_selected_columns =
+        (gint (*) (AtkTable *table, gint **selected)) NULL;
+    klass-> get_selected_rows =
+        (gint (*) (AtkTable *table, gint **selected)) NULL;
+    klass-> is_column_selected =
+        (gboolean (*) (AtkTable *table, gint column)) NULL;
+    klass-> is_row_selected =
+        (gboolean (*) (AtkTable *table, gint row)) NULL;
+    klass-> is_selected =
+        (gboolean (*) (AtkTable *table, gint row, gint column)) NULL;
+    klass-> add_row_selection =
+        (gboolean (*) (AtkTable *table, gint row)) NULL;
+    klass-> remove_row_selection =
+        (gboolean (*) (AtkTable *table, gint row)) NULL;
+    klass-> add_column_selection =
+        (gboolean (*) (AtkTable *table, gint column)) NULL;
+    klass-> remove_column_selection =
+        (gboolean (*) (AtkTable *table, gint column)) NULL;
+}
+
+static void
+table_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+    MyAtkTable *self = (MyAtkTable *)instance;
+    
+    self->disposed = FALSE;
+}
+
+static void
+my_atk_table_dispose (GObject *obj)
+{
+    MyAtkTable *self = (MyAtkTable *)obj;
+
+    if (self->disposed) 
+    {
+        return;
+    }
+    
+    /* Make sure dispose does not run twice. */
+    self->disposed = TRUE;
+
+    /* Chain up to the parent class */
+    G_OBJECT_CLASS (parent_class_table)->dispose (obj);
+}
+
+static void
+my_atk_table_finalize (GObject *obj)
+{
+    /* Chain up to the parent class */
+    G_OBJECT_CLASS (parent_class_table)->finalize (obj);
+}
+
+static void
+my_atk_table_class_init (gpointer g_class, gpointer g_class_data)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
+    MyAtkTableClass *klass = MY_ATK_TABLE_CLASS (g_class);
+
+    gobject_class->dispose = my_atk_table_dispose;
+    gobject_class->finalize = my_atk_table_finalize;
+
+    parent_class_table = g_type_class_peek_parent (klass);
+}
+
+GType 
+my_atk_table_get_type (void)
+{
+    static GType type = 0;
+    if (type == 0) 
+    {
+        static const GTypeInfo info = 
+        {
+            sizeof (MyAtkTableClass),
+            NULL,   /* base_init */
+            NULL,   /* base_finalize */
+            my_atk_table_class_init, /* class_init */
+            NULL,   /* class_finalize */
+            NULL,   /* class_data */
+            sizeof (MyAtkTable),
+            0,      /* n_preallocs */
+            table_instance_init    /* instance_init */
+        };
+                
+        static const GInterfaceInfo iface_info = 
+        {
+            (GInterfaceInitFunc) table_interface_init,    /* interface_init */
+            NULL,                                       /* interface_finalize */
+            NULL                                        /* interface_data */
+        };
+        type = g_type_register_static (MY_TYPE_ATK_OBJECT,
+                                       "MyAtkTableType",
+                                       &info, 0);
+        g_type_add_interface_static (type,
+                                     ATK_TYPE_TABLE,
+                                     &iface_info);
+    }
+    return type;
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-table.h pyatspi2/tests/dummyatk/my-atk-table.h
--- pyatspi2.old/tests/dummyatk/my-atk-table.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-table.h	2019-08-27 19:10:03.877588542 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MY_ATK_TABLE_H
+#define MY_ATK_TABLE_H
+
+#include <glib-object.h>
+#include <atk/atk.h> 
+#include <my-atk-object.h>
+    
+#define MY_TYPE_ATK_TABLE             (my_atk_table_get_type ())
+#define MY_ATK_TABLE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_ATK_TABLE, MyAtkTable))
+#define MY_ATK_TABLE_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MY_TYPE_ATK_TABLE, MyAtkTableClass))
+#define MY_IS_ATK_TABLE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_ATK_TABLE))
+#define MY_IS_ATK_TABLE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MY_TYPE_ATK_TABLE))
+#define MY_ATK_TABLE_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MY_TYPE_ATK_TABLE, MyAtkTableClass))
+
+#define NROWS 4     /* row count */
+#define NCOLS 5     /* column count */
+
+static gint ids[NROWS][NCOLS] = 
+    { {0,  1,  2,  2,  3},
+      {4,  5,  6,  7,  8},
+      {9,  9, 10, 11, 12},
+      {9,  9, 13, 14, -1} };
+      
+static gint row_ext[NROWS][NCOLS] = 
+    { {1,  1,  1,  1,  1},
+      {1,  1,  1,  1,  1},
+      {2,  2,  1,  1,  1},
+      {2,  2,  1,  1,  1} };
+
+static gint col_ext[NROWS][NCOLS] = 
+    { {1,  1,  2,  2,  1},
+      {1,  1,  1,  1,  1},
+      {2,  2,  1,  1,  1},
+      {2,  2,  1,  1,  1} };
+
+#define NCHILDREN 16    /* child object count */
+
+// default string values
+#define DEF_CAPTION_TEXT    "Default table caption"
+#define DEF_SUMMARY_TEXT    "Default table summary"
+#define DEF_ROW_DESCR_TPL   "Row No%d"
+#define DEF_COL_DESCR_TPL   "Column No%d"
+
+/* row and column headers */
+typedef struct
+{
+    AtkObject* hdr;
+    gboolean selected;  /* TRUE if the row/column is selected, FALSE otherwise */
+} TestSimpleHeaderStruct;
+
+/* This struct represents a table cell */
+typedef struct
+{
+    MyAtkObject* elem;   /* the element */
+    guint ext_row;           /* its row extent */
+    guint ext_col;           /* its column extent */
+} TestSimpleCell;
+
+typedef struct _MyAtkTable MyAtkTable;
+typedef struct _MyAtkTableClass MyAtkTableClass;
+
+struct _MyAtkTable 
+{
+    MyAtkObject parent;
+        
+    gboolean disposed;
+    
+    MyAtkObject* child[NCHILDREN];
+    MyAtkObject* not_a_child;
+    TestSimpleHeaderStruct row[NROWS];
+    TestSimpleHeaderStruct col[NCOLS];
+    guint nrows;
+    guint ncols;
+    AtkObject* caption;
+    AtkObject* summary;
+};
+
+struct _MyAtkTableClass 
+{
+    MyAtkObjectClass parent;
+};
+
+GType 
+my_atk_table_get_type (void);
+
+#endif /*MY_ATK_TABLE_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-text.c pyatspi2/tests/dummyatk/my-atk-text.c
--- pyatspi2.old/tests/dummyatk/my-atk-text.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-text.c	2019-08-27 19:10:03.877588542 +0200
@@ -0,0 +1,1309 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#include <atk/atk.h>
+#include <string.h>
+#include <limits.h>
+#include <useful_functions.h>
+
+#include "my-atk-text.h"
+//*************************implementation***********************
+
+//Attributes
+/*
+ * Auxiliary functions create/copy/print/free structures
+ * Use the same naming principe, as atk, but without 'atk' prefix
+ */
+ //AtkAttribute
+AtkAttribute* attribute_new(const gchar* name, const gchar* value)
+{
+    AtkAttribute* attr = g_malloc(sizeof(AtkAttribute));
+    if(attr == NULL) return NULL;
+    attr->name = g_strdup(name);
+    attr->value = g_strdup(value);
+    return attr;
+}
+AtkAttribute* attribute_copy(AtkAttribute* attr)
+{
+    return attribute_new(attr->name, attr->value);
+}
+void attribute_print(AtkAttribute* attr)
+{
+    TRACE("name=%s, value=%s", attr->name, attr->value);
+}
+
+//AtkAttributeSet
+AtkAttributeSet* attribute_set_copy(AtkAttributeSet* attr)
+{
+    GSList *tmp;
+    AtkAttributeSet* result = g_slist_copy(attr);
+    for(tmp = result; tmp != NULL; tmp = tmp->next)
+        tmp->data = attribute_copy((AtkAttribute*)tmp->data);
+    return result;
+}
+void attribute_set_print(AtkAttributeSet *set)
+{
+    if(set == NULL) 
+       TRACE0("(empty)");
+    else 
+       g_slist_foreach(set, (GFunc)attribute_print, NULL);
+}
+
+// STATIC FUNCTIONS
+//
+//auxiliary functions for search tokens
+//Number of different characters
+#define TABLE_SIZE 256  
+//modificator static isn't used because this tables will be use in tests
+/*static*/ gboolean  table_word_symbols[TABLE_SIZE],
+                     table_sentence_symbols[TABLE_SIZE],
+                     table_line_symbols[TABLE_SIZE];
+static gboolean *tables[7]={NULL,
+    table_word_symbols,
+    table_word_symbols,
+    table_sentence_symbols,
+    table_sentence_symbols,
+    table_line_symbols,
+    table_line_symbols
+    };
+
+static gboolean current_token(const gchar* str, gint offset, gint *token_start, gint *token_end,
+    const gboolean table_token_symbols[TABLE_SIZE])
+{
+    const gchar *current = str + offset;
+    if(!table_token_symbols[(guchar)*current])
+    {
+        return FALSE;
+    }
+    for( --current; (current >= str) && table_token_symbols[(guchar)*current]; --current);
+    *token_start = current - str + 1;
+    for(current = str + offset + 1;
+        (*current != 0) && table_token_symbols[(guchar)*current]; ++current);
+    *token_end = current - str;
+    return TRUE;
+}
+static gboolean next_token(const gchar* str, gint offset, gint *token_start, gint *token_end,
+    const gboolean table_token_symbols[TABLE_SIZE])
+{
+    const gchar *current = str + offset;
+    for( ; (*current != 0) && table_token_symbols[(guchar)*current]; ++current);
+    if(*current == 0)
+        return FALSE;
+    for(++current ; (*current != 0) && !table_token_symbols[(guchar)*current]; ++current);
+    if(!table_token_symbols[(guchar)*current])
+        return FALSE;
+    return current_token(str, current - str, token_start, token_end, table_token_symbols);
+}
+static gboolean previous_token(const gchar* str, gint offset, gint *token_start, gint *token_end,
+    const gboolean table_token_symbols[TABLE_SIZE])
+{
+    const gchar *current = str + offset;
+    for( ; (current > str) && table_token_symbols[(guchar)*current]; --current);
+    if(current == str)
+        return FALSE;
+    for( ; (current > str) && !table_token_symbols[(guchar)*current]; --current);
+    if(!table_token_symbols[(guchar)*current])
+        return FALSE;
+    return current_token(str, current - str, token_start, token_end, table_token_symbols);
+}
+
+
+//Range: type of data, containing in list of attributes
+typedef struct
+{
+    gint start,end;//range, containing this attributes
+    AtkAttributeSet* attributeSet;
+} Range;
+//auxiliary functions for ranges
+Range* range_new(gint start, gint end)
+{
+    Range *range = g_malloc(sizeof(Range));
+    range->start = start;
+    range->end = end;
+    range->attributeSet = NULL;
+    return range;
+}
+
+void range_free(Range* range)
+{
+    atk_attribute_set_free(range->attributeSet);
+    g_free(range);
+}
+void range_print(const Range*range)
+{
+    TRACE("[%d,%d):", range->start, range->end);
+    attribute_set_print(range->attributeSet);
+}
+//only for correct list of ranges - ranges shouldn't intersect
+gint range_compare(const Range* range1, const Range* range2)
+{
+    return range1->start - range2->start;//never equal
+}
+//Bounds of text
+void text_bounds_init(TextBounds *bounds)
+{
+    bounds->base_x = 0;
+    bounds->base_y = 0;
+    bounds->pixels_above_line = 2;
+    bounds->pixels_below_line = 3;
+    bounds->size = 8;
+    bounds->pixels_between_characters = 1;
+    bounds->width = 3;
+}
+
+//auxiliary function - create new range according to start_offset and end_offset
+AtkTextRange* text_range_new(AtkText* text,
+    gint start_offset, gint end_offset, AtkCoordType coord_type)
+{
+    AtkTextRange* range = g_malloc(sizeof(AtkTextRange));
+    if(range == NULL) return NULL;
+    range->start_offset = start_offset;
+    range->end_offset = end_offset;
+    range->content = atk_text_get_text(text, start_offset, end_offset);
+    atk_text_get_range_extents(text, start_offset, end_offset, coord_type, &range->bounds);
+    return range;
+}
+// Returns number of line, which contain given character.
+// Also return relative offset - offset of this character from start of the line
+gint get_character_line(MyAtkText *text, gint offset, gint *relative_offset)
+{
+    gint result = 0;
+    //simple realization - counts lines from start of the text, until reaches offset
+    const guchar *text_str = (guchar*)text->str; 
+    gboolean state_FSM = table_line_symbols[text_str[0]];
+    gint i, last_line_start = 0;
+    for(i = 1; i <= offset; state_FSM = table_line_symbols[text_str[i++]])
+    {
+        if(state_FSM)continue;
+        result++;
+        last_line_start = i;
+    }
+    if(relative_offset != NULL) *relative_offset = offset - last_line_start;
+    return result;
+}
+// Compute extent of character,
+// as it was at line 'line' and at offset 'relative_offset' in that line
+//(geometry) 
+void get_extents(MyAtkText *text, gint line, gint relative_offset, AtkTextRectangle *rect)
+{
+    rect->x = text->bounds.base_x + relative_offset * 
+        (text->bounds.width + text->bounds.pixels_between_characters);
+    rect->y = text->bounds.base_y + text->bounds.pixels_above_line + line *
+        (text->bounds.size + text->bounds.pixels_below_line + text->bounds.pixels_above_line);
+    rect->width = text->bounds.width;
+    rect->height = text->bounds.size; 
+}
+//return line, corresponding to given y-coordinate
+gint get_point_line(MyAtkText *text, gint y)
+{
+    //slightly differ from invers operation
+    if(y - text->bounds.base_y < 0)return -1;
+    return  (y - text->bounds.base_y)
+        /(text->bounds.size + text->bounds.pixels_below_line + text->bounds.pixels_above_line);
+}
+// Returns offset from left boundary of text, correspondind to x-coordinate
+gint get_point_relative_offset(MyAtkText *text, gint x)
+{
+    //slightly differ from invers operation
+    if(x - text->bounds.base_x < 0)return -1;
+    return (x - text->bounds.base_x) 
+        /(text->bounds.width + text->bounds.pixels_between_characters);
+}
+// Returns offset where given line start(even if this line is empty)
+// If line number too small(<0)return -1, if too big - return length of the text 
+gint get_offset_at_line_start(MyAtkText *text, gint line)
+{
+    gint i;
+    if(line < 0)return -1;
+    if(line == 0)return 0;
+    gint len = my_strlen(text->str);
+    guchar *str = (guchar*)text->str;
+    gint current_line = 0;
+    gboolean state_FSM = table_line_symbols[str[0]];
+    for(i = 1; i < len; state_FSM = table_line_symbols[str[i++]])
+    {
+        if(state_FSM || ++current_line != line)continue;
+        return i;
+    }
+    return len;
+    
+}
+// Return offset of character at the given line and at the given offset at this line
+// If such character doesn't exist, return -1 
+gint get_offset_at_line(MyAtkText *text, gint line, gint relative_offset)
+{
+    gint j;
+    if(line < 0 || relative_offset < 0)return -1; 
+    const guchar* str = (guchar*)text->str;
+    gint len = my_strlen(text->str);
+    gint offset_at_line_start = get_offset_at_line_start(text, line);
+    if(offset_at_line_start + relative_offset >= len)return -1;
+    for(j = 0; j <= relative_offset; j++) 
+        if(!table_line_symbols[str[offset_at_line_start + j]])
+            return -1;
+    return offset_at_line_start + relative_offset;
+}
+/*
+ * Count ranges of text, which clipping by rel_start_offset and relative_end_offset.
+ * 'offset' stands start of search(start of first line),
+ * number_of_lines - maximum number of lines for search.
+ * If 'ranges' not NULL, writes ranges to it. 'coord_type' used only in this case.
+ */
+gint count_ranges(MyAtkText *text, gint offset, gint rel_start_offset, gint rel_end_offset, 
+                 gint number_of_lines, AtkTextRange** ranges, AtkCoordType coord_type)
+{
+    guchar *str = (guchar*)text->str;
+    gint len = my_strlen(text->str);
+    
+    gint number_of_ranges = 0;
+    gint current_line = 0;
+    gint current_line_start = offset;
+    for(;(current_line < number_of_lines) && (current_line_start < len); current_line ++)
+    {
+        if(!table_line_symbols[str[current_line_start]])
+        {
+            current_line_start++;
+            continue;
+        }
+        gint start_offset,end_offset;
+        gchar *tmp_str = atk_text_get_text_at_offset((AtkText*)text, current_line_start,
+            ATK_TEXT_BOUNDARY_LINE_END, &start_offset, &end_offset);
+        g_free(tmp_str);
+        if(end_offset - current_line_start > rel_start_offset)
+        {
+            if(ranges != NULL)
+            {
+                gint range_start_offset = current_line_start + rel_start_offset;
+                gint range_end_offset =  current_line_start + rel_end_offset + 1;
+                if(range_end_offset > end_offset)
+                    range_end_offset = end_offset;
+                //add element    
+                ranges[number_of_ranges] = text_range_new((AtkText*)text, 
+                    range_start_offset, range_end_offset, coord_type);
+            }
+            number_of_ranges++;
+        }
+        current_line_start = end_offset + 1;
+    }
+    if(ranges != NULL) ranges[number_of_ranges] = NULL;
+    return number_of_ranges;
+}
+
+//"free"-functions(for internal using, because them don't emit signals)
+void my_atk_text_free_run_attributes(MyAtkText *text)
+{
+    g_list_foreach(text->attributes, (GFunc)range_free, NULL);
+    g_list_free(text->attributes);
+    text->attributes = NULL;
+}
+void my_atk_text_free_default_attributes(MyAtkText *text)
+{
+    atk_attribute_set_free(text->default_attributes);
+    text->default_attributes = NULL;
+}
+void my_atk_text_clear_selections(MyAtkText *text)
+{
+    if(text->selections->len != 0)
+        g_array_remove_range(text->selections, 0, text->selections->len);
+}
+void table_symbols_init()
+{
+    //word
+    gint i;
+    for(i = TABLE_SIZE - 1;i > 0 ; --i)
+        table_word_symbols[i] = g_ascii_isalnum(i);
+    table_word_symbols['\0'] = FALSE;
+    //sentence
+    for(i = TABLE_SIZE - 1;i >= 0x20; --i)
+        table_sentence_symbols[i] = TRUE;
+    table_sentence_symbols['.'] = FALSE; 
+    table_sentence_symbols['!'] = FALSE;
+    table_sentence_symbols['?'] = FALSE;
+    for(i = 0x1f;i > 0; --i)
+        table_sentence_symbols[i] = FALSE;
+    table_sentence_symbols['\0'] = FALSE;
+    //line
+    for(i = TABLE_SIZE - 1;i > 0 ; --i)
+        table_line_symbols[i] = TRUE;
+    table_line_symbols['\n'] = FALSE;
+    table_line_symbols['\0'] = FALSE;
+}
+void correct_selections_after_insert(MyAtkText *text, gint position, gint length)
+{
+    gint i;
+    GArray* selections = text->selections;
+    for(i = selections->len - 1; i >=0; i--)
+    {
+        TextSelection* sel  = &g_array_index(selections, TextSelection, i);
+        if(sel->end_offset >= position) sel->end_offset+= length;
+        if(sel->start_offset >= position) sel->start_offset+= length;
+        else break;
+    }
+}
+void correct_selections_after_delete(MyAtkText *text, gint position, gint length)
+{
+    gint i;
+    GArray* selections = text->selections;
+    for(i = selections->len - 1; i >=0; i--)
+    {
+        TextSelection* sel  = &g_array_index(selections, TextSelection, i);
+        if(sel->start_offset >= position)
+        {
+             if(sel->start_offset >= position + length)
+             {
+                sel->start_offset-= length;
+                sel->end_offset-= length;
+             }
+             //position <= sel->start_offset < position + length
+             else if(sel->end_offset > position + length)
+             {
+                sel->start_offset = position;
+                sel->end_offset -= length;
+             }
+             else
+             {
+                g_array_remove_index(selections, i);
+             }
+             continue;  
+        }
+        /*sel->start_offset < position*/
+        if(sel->end_offset > position + length) sel->end_offset-= length;
+        else if(sel->end_offset > position) sel->end_offset = position;
+        break;
+    }
+}
+void correct_attributes_after_insert(MyAtkText* text, gint position, gint length)
+{
+    GList *attributes = text->attributes;
+    GList *tmp;
+    //before inserted position
+    for(tmp = attributes; tmp != NULL; tmp = tmp -> next)
+    {
+        Range* range = (Range*)tmp->data;
+        if(range->end <= position)continue;
+        //range->end > position
+        if(range->start < position)
+            range->start -= length;//will be restore in the next loop
+        break;
+    }
+    //after inserted position
+    for(; tmp != NULL; tmp = tmp -> next)
+    {
+        Range* range = (Range*)tmp->data;
+        range->end += length;
+        range->start += length;
+    }
+}
+void correct_attributes_after_delete(MyAtkText* text, gint position, gint length)
+{
+    GList *attributes = text->attributes;
+    GList *tmp = attributes;
+    //before deleting range
+    for(tmp = attributes; tmp != NULL; tmp = tmp->next)
+    {
+        Range* range  = (Range*)tmp->data;
+        if(range->end <= position) continue;
+        if(range->start < position)
+        {
+             if(range->end > position + length) range->end -= length;
+             else range->end = position;
+             tmp = tmp->next;
+        }
+        break;
+    }
+    //at deleting range
+    while(tmp != NULL)
+    {
+        Range* range = (Range*)tmp->data;
+        if(range->start >= position + length) break;
+        if(range->end <= position + length)
+        {
+            GList *tmp1 = tmp->next;
+            range_free(range);
+            attributes = g_list_remove_link(attributes, tmp);
+            tmp = tmp1;
+            continue;
+        }
+        //range->end > position + length
+        //range->start < position + length
+        range->start = position + length;//will be restored in next loop
+        break;
+    }
+    //after deleting range
+    for(;tmp != NULL; tmp = tmp->next)
+    {
+        Range* range = (Range*)tmp->data;
+        range->end -= length;
+        range->start -= length;
+    }
+    text->attributes = attributes;
+}
+void correct_caret_after_insert(MyAtkText* text, gint position, gint length)
+{
+    if(text->caret_offset > position)text->caret_offset += length;
+}
+void correct_caret_after_delete(MyAtkText* text, gint position, gint length)
+{
+    if(text->caret_offset >= position + length)text->caret_offset -= length;
+    else if(text->caret_offset > position) text->caret_offset = position;
+}
+
+// Implementation of virtual functions
+//******************************my_atk_text_get_character_count*************************
+static gint my_atk_text_get_character_count(AtkText *text)
+{
+    MyAtkText *self = (MyAtkText*)text;
+    return my_strlen(self->str);
+}
+//**************************************my_atk_text_get_text*****************************
+static gchar* my_atk_text_get_text(AtkText *text, gint start_offset, gint end_offset)
+{
+    gchar *str = ((MyAtkText*)text)->str;
+    if((start_offset < 0) || (end_offset > my_strlen(str)) || (end_offset <= start_offset))
+    {
+        //incorrect bounds
+        return NULL;
+    }
+    return g_strndup(str + start_offset, end_offset - start_offset);
+    
+}
+//*******************************my_atk_text_get_character_at_offset************************
+static gunichar my_atk_text_get_character_at_offset(AtkText *text, gint offset)
+{
+    gchar *str = ((MyAtkText*)text)->str;
+    if(offset < 0 || offset >= my_strlen(str))
+    {
+        return 0;
+    }
+    return (gunichar)str[offset];
+}
+// In the next 3 functions some code is commented for verify tests themselves on 'mutants'
+// in realization.
+//******************************my_atk_text_get_text_after_offset***************************
+static gchar* my_atk_text_get_text_after_offset(AtkText *text, gint offset,
+    AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset)
+{
+    gchar *str = ((MyAtkText*)text)->str;
+    gint len = my_strlen(str);
+    if((offset < 0) || (offset >= len))
+    {
+        return NULL;//incorrect offset
+    }
+    
+    // This variable is set in switch statement. If after that statement variable is TRUE,
+    // then return text from 'strat_offset' to 'end_offset'. Otherwise NULL will be returned.
+    gboolean is_successed = TRUE;
+    
+    gint start_tmp;
+    gint end_tmp;
+    
+    switch(boundary_type)
+    {
+    case ATK_TEXT_BOUNDARY_CHAR:
+        if(offset + 1 == len)
+        {
+            is_successed = FALSE;
+            break;
+        }
+        *start_offset = offset + 1;
+        *end_offset = offset + 2;
+        is_successed = TRUE;
+        break;
+    case ATK_TEXT_BOUNDARY_WORD_START:
+    case ATK_TEXT_BOUNDARY_SENTENCE_START:
+    case ATK_TEXT_BOUNDARY_LINE_START:
+        if(!next_token(str, offset, start_offset, &end_tmp, tables[boundary_type]))
+        {
+            //debug
+//            if(current_token(str, offset, start_offset, end_offset, tables[boundary_type]))
+//            {
+//                is_successed = TRUE;
+//                break;
+//            }
+            is_successed = FALSE;
+            break;
+        }
+        if(!next_token(str, end_tmp, end_offset, &end_tmp, tables[boundary_type]))
+        {
+            *end_offset = len;
+        }
+        is_successed = TRUE;
+        //debug
+//        (*start_offset)++;
+//        if(*start_offset > 10) ++(*start_offset);
+        break;
+    case ATK_TEXT_BOUNDARY_WORD_END:
+    case ATK_TEXT_BOUNDARY_SENTENCE_END:
+    case ATK_TEXT_BOUNDARY_LINE_END:
+        if(!current_token(str, offset, &start_tmp, start_offset, tables[boundary_type]))
+        {
+            if(!next_token(str, offset, &start_tmp, start_offset, tables[boundary_type]))
+            {
+                is_successed = FALSE;
+                break;
+            }
+        }
+        //debug
+//        else if(*start_offset > strlen(str) - 7)
+//        {
+//           *end_offset = *start_offset + 3;
+//            is_successed = TRUE;
+//           break;
+//        }
+        if(!next_token(str, *start_offset, &start_tmp, end_offset, tables[boundary_type]))
+        {
+            is_successed = FALSE;
+            break;
+        }
+        //debug
+//        --(*start_offset);
+        is_successed = TRUE;
+        
+        break;
+    default:
+        is_successed = FALSE;
+    }
+
+    if(is_successed)
+    {
+        return my_atk_text_get_text(text, *start_offset, *end_offset);
+    }
+    else
+    {
+        return NULL;
+    }
+}
+//*******************************my_atk_text_get_text_at_offset*******************************
+static gchar* my_atk_text_get_text_at_offset(AtkText *text, gint offset,
+    AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset)
+{
+    gchar *str = ((MyAtkText*)text)->str;
+    gint len = my_strlen(str);
+    if((offset < 0) || (offset >= len))
+    {
+        return NULL;
+    }
+    
+    // This variable is set in switch statement. If after that statement variable is TRUE,
+    // then return text from 'strat_offset' to 'end_offset'. Otherwise NULL will be returned.
+    gboolean is_successed = TRUE;
+    
+    gint start_tmp;
+    gint end_tmp;
+    
+    switch(boundary_type)
+    {
+    case ATK_TEXT_BOUNDARY_CHAR:
+        *start_offset = offset;
+        *end_offset = offset + 1;
+        is_successed = TRUE;
+        break;
+    case ATK_TEXT_BOUNDARY_WORD_START:
+    case ATK_TEXT_BOUNDARY_SENTENCE_START:
+    case ATK_TEXT_BOUNDARY_LINE_START:
+        if(!current_token(str, offset, start_offset, &end_tmp, tables[boundary_type]))
+        {
+            if(!previous_token(str, offset, start_offset, &end_tmp, tables[boundary_type]))
+            {
+                is_successed = FALSE;
+                break;
+            }
+        }
+        if(!next_token(str, offset, end_offset, &end_tmp, tables[boundary_type]))
+        {
+            *end_offset = len;
+        }
+        is_successed = TRUE;
+        break;
+    case ATK_TEXT_BOUNDARY_WORD_END:
+    case ATK_TEXT_BOUNDARY_SENTENCE_END:
+    case ATK_TEXT_BOUNDARY_LINE_END:
+        if(!current_token(str, offset, &start_tmp, end_offset, tables[boundary_type]))
+        {
+            if(!next_token(str, offset, &start_tmp, end_offset, tables[boundary_type]))
+            {
+                is_successed = FALSE;
+                break;
+            }
+        }
+        if(!previous_token(str, start_tmp, &start_tmp, start_offset, tables[boundary_type]))
+        {
+            *start_offset = 0;
+        }
+        is_successed = TRUE;
+        //debug
+//        ++(*start_offset);
+        break;
+    default:
+        is_successed = FALSE;
+    }
+
+    if(is_successed)
+    {
+        //debug
+//        if(boundary_type == ATK_TEXT_BOUNDARY_LINE_START)
+//            return my_atk_text_get_text(text, ++(*start_offset), *end_offset);
+        return my_atk_text_get_text(text, *start_offset, *end_offset);
+    }
+    else
+    {
+        return NULL;
+    }
+}
+//***********************************my_atk_text_get_text_before_offset******************
+static gchar* my_atk_text_get_text_before_offset(AtkText *text, gint offset,
+    AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset)
+{
+    gchar *str = ((MyAtkText*)text)->str;
+    gint len = my_strlen(str);
+    if((offset < 0) || (offset >= len))
+    {
+        return NULL;
+    }
+    
+    // This variable is set in switch statement. If after that statement variable is TRUE,
+    // then return text from 'strat_offset' to 'end_offset'. Otherwise NULL will be returned.
+    gboolean is_successed = TRUE;
+    
+    gint start_tmp;
+    gint end_tmp;
+    
+    switch(boundary_type)
+    {
+    case ATK_TEXT_BOUNDARY_CHAR:
+        if(offset == 0)
+        {
+            is_successed = FALSE;
+            break;
+        }
+        *start_offset = offset - 1;
+        *end_offset = offset;
+        is_successed = TRUE;
+        break;
+    case ATK_TEXT_BOUNDARY_WORD_START:
+    case ATK_TEXT_BOUNDARY_SENTENCE_START:
+    case ATK_TEXT_BOUNDARY_LINE_START:
+        if(!current_token(str, offset, end_offset, &end_tmp, tables[boundary_type]))
+        {
+            if(!previous_token(str, offset, end_offset, &end_tmp, tables[boundary_type]))
+            {
+                is_successed = FALSE;
+                break;
+            }
+        }
+        if(!previous_token(str, *end_offset, start_offset, &end_tmp, tables[boundary_type]))
+        {
+            is_successed = FALSE;
+            break;    
+        }
+        is_successed = TRUE;
+        //debug
+//        ++(*start_offset);
+        break;
+    case ATK_TEXT_BOUNDARY_WORD_END:
+    case ATK_TEXT_BOUNDARY_SENTENCE_END:
+    case ATK_TEXT_BOUNDARY_LINE_END:
+        if(!previous_token(str, offset, &start_tmp, end_offset, tables[boundary_type]))
+        {
+            is_successed = FALSE;
+            break;
+        }
+        if(!previous_token(str, start_tmp, &start_tmp, start_offset, tables[boundary_type]))
+        {
+            *start_offset = 0;
+        }
+        is_successed = TRUE;
+        break;
+    default:
+        is_successed = FALSE;
+    }
+
+    if(is_successed)
+    {
+        return my_atk_text_get_text(text, *start_offset, *end_offset);
+    }
+    else
+    {
+        return NULL;
+    }
+}
+//*********************************my_atk_text_get_run_attributes*****************
+AtkAttributeSet* my_atk_text_get_run_attributes(AtkText* text, gint offset,
+    gint *start_offset, gint *end_offset)
+{
+    GList *tmp;
+    GList *attributes = ((MyAtkText*)text)->attributes;
+    if(offset < 0 || offset >= my_atk_text_get_character_count(text))
+    {
+        TRACE0("Incorrect value of offset.");
+        return NULL;
+    }
+    gint start = -1, end = -1;
+    for(tmp = attributes; tmp != NULL; tmp = tmp->next)
+    {
+        Range* range = (Range*)(tmp->data); 
+        if(range->end <= offset)
+        {
+             start = range->end;
+             continue;
+        }
+        if(range->start > offset)
+        {
+             end = range->start;
+             break;
+        }
+        
+        *start_offset = range->start;
+        *end_offset = range->end;
+        return attribute_set_copy(range->attributeSet);
+    }    
+    *start_offset = (start == -1) ? 0 : start;
+    *end_offset = (end == -1) ? my_atk_text_get_character_count(text) : end;
+    return NULL;
+}
+//*********************************my_atk_text_get_default_attributes*****************
+AtkAttributeSet* my_atk_text_get_default_attributes(AtkText* text)
+{
+    return attribute_set_copy(((MyAtkText*)text)->default_attributes);
+}
+//*********************************my_atk_text_get_character_extents*****************
+void my_atk_text_get_character_extents(AtkText* text, gint offset, gint *x, gint *y,
+    gint *width, gint *height, AtkCoordType coord_type)
+{
+    AtkTextRectangle result;
+    gint relative_offset, line;
+    line = get_character_line((MyAtkText*)text, offset, &relative_offset);
+    get_extents((MyAtkText*)text, line, relative_offset, &result);
+    *x = result.x;
+    *y = result.y;
+    *width = result.width;
+    *height = result.height;
+}
+//*******************************my_atk_text_get_range_extents************************
+void my_atk_text_get_range_extents(AtkText *text, gint start_offset, gint end_offset,
+    AtkCoordType coord_type, AtkTextRectangle *rect)
+{
+    //simple - union of extents of the characters, contained in this range
+    AtkTextRectangle result, bounds_tmp;
+    gint i;
+
+    atk_text_get_character_extents (text, start_offset,
+                                  &result.x, &result.y,
+                                  &result.width, &result.height,
+                                  coord_type);
+
+    for (i = start_offset + 1; i < end_offset; i++)
+    {
+        my_atk_text_get_character_extents (text, i,&bounds_tmp.x, &bounds_tmp.y, 
+            &bounds_tmp.width, &bounds_tmp.height, coord_type);
+        
+        if(bounds_tmp.x < result.x)
+        {
+            //corrects left boundary
+            result.width += result.x - bounds_tmp.x;
+            result.x = bounds_tmp.x; 
+        }
+        if(bounds_tmp.x + bounds_tmp.width > result.x + result.width)
+        {
+            //corrects right boundary
+            result.width = bounds_tmp.x + bounds_tmp.width - result.x;
+        }
+        if(bounds_tmp.y < result.y)
+        {
+            //corrects top boundary
+            result.height += result.y - bounds_tmp.y;
+            result.y = bounds_tmp.y; 
+        }
+        if(bounds_tmp.y + bounds_tmp.height > result.y + result.height)
+        {
+            //corrects buttom boundary
+            result.height = bounds_tmp.y + bounds_tmp.height - result.y;
+        }
+    }
+    *rect = result;
+}
+//**********************************my_atk_text_get_offset_at_point*********************
+gint my_atk_text_get_offset_at_point(AtkText* text, gint x, gint y, AtkCoordType coord_type)
+{
+    gint line, relative_offset;
+
+    line = get_point_line((MyAtkText*)text, y);
+    relative_offset = get_point_relative_offset((MyAtkText*)text, x);
+
+    return get_offset_at_line((MyAtkText*)text, line, relative_offset);
+}
+//*****************************my_atk_text_get_bounded_ranges******************************
+AtkTextRange** my_atk_text_get_bounded_ranges(AtkText *text, AtkTextRectangle *rect,
+    AtkCoordType coord_type, AtkTextClipType x_clip_type, AtkTextClipType y_clip_type)
+{
+    MyAtkText *self = (MyAtkText*)text;
+    
+    gint start_line, end_line, start_rel_offset, end_rel_offset;
+    AtkTextRange** result;    
+    gint len = my_strlen(self->str);
+//macro for simplify return empty ranges when fail to do smth
+#define RETURN_EMTPY_RANGES {result = g_malloc(sizeof(AtkTextRange*));result[0] = NULL;return result;}
+    //start line
+    start_line = (y_clip_type == ATK_TEXT_CLIP_NONE) || (y_clip_type == ATK_TEXT_CLIP_MAX)
+        ? 0 : get_point_line(self, rect->y);
+    if(start_line < 0) start_line = 0;
+    //end line
+    end_line = (y_clip_type == ATK_TEXT_CLIP_NONE) || (y_clip_type == ATK_TEXT_CLIP_MIN)
+        ? G_MAXINT/2 : get_point_line(self, rect->y  + rect->height);
+    if(end_line < 0) RETURN_EMTPY_RANGES;
+    //start relative offset
+    start_rel_offset = (x_clip_type == ATK_TEXT_CLIP_NONE) || (x_clip_type == ATK_TEXT_CLIP_MAX)
+        ? 0 : get_point_relative_offset(self, rect->x);
+    if(start_rel_offset < 0) start_rel_offset = 0;
+    //end relative offset
+    end_rel_offset = (x_clip_type == ATK_TEXT_CLIP_NONE) || (x_clip_type == ATK_TEXT_CLIP_MIN)
+        ? G_MAXINT/2 : get_point_relative_offset(self, rect->x + rect->width);
+    if(end_rel_offset < 0) RETURN_EMTPY_RANGES;
+    //start offset(at the start of 'start_line')
+    gint start_offset = get_offset_at_line_start(self, start_line);
+    if(start_offset + start_rel_offset >= len) RETURN_EMTPY_RANGES;
+ 
+    //count ranges
+    gint number_of_ranges = count_ranges(self, start_offset,
+        start_rel_offset, end_rel_offset, end_line - start_line + 1, NULL, coord_type);
+    //create array(with just getting size)
+    result = g_malloc(sizeof(AtkTextRange*) * (number_of_ranges + 1));
+    //write ranges
+    count_ranges(self, start_offset,
+        start_rel_offset, end_rel_offset, end_line - start_line + 1, result, coord_type);
+#undef RETURN_EMPTY_RANGES
+    return result;
+}
+
+//********************************my_atk_text_get_n_selections*******************************
+gint my_atk_text_get_n_selections(AtkText *text)
+{
+    MyAtkText *self = (MyAtkText*)text;
+    return self->selections->len;
+}
+
+//********************************my_atk_text_get_selection*******************************
+gchar* my_atk_text_get_selection(AtkText *text,
+    gint selection_num, gint *start_offset, gint *end_offset)
+{
+    MyAtkText *self = (MyAtkText*)text;
+    GArray *selections = self->selections;
+    if(selection_num < 0 || selection_num >= selections->len) return NULL;
+    *start_offset = g_array_index(selections, TextSelection, selection_num).start_offset;
+    *end_offset = g_array_index(selections, TextSelection, selection_num).end_offset;
+    return my_atk_text_get_text(text, *start_offset, *end_offset);
+}
+//********************************my_atk_text_remove_selection*******************************
+gboolean my_atk_text_remove_selection(AtkText *text, gint selection_num)
+{
+    MyAtkText *self = (MyAtkText*)text;
+    GArray *selections = self->selections;
+    if(selection_num < 0 || selection_num >= selections->len) return FALSE;
+    g_array_remove_index(selections, selection_num);
+    
+    g_signal_emit_by_name(text, "text-selection-changed");
+    return TRUE;
+}
+//********************************my_atk_text_add_selection*******************************
+gboolean my_atk_text_add_selection(AtkText *text, gint start_offset, gint end_offset)
+{
+    if(start_offset < 0 || end_offset > my_atk_text_get_character_count(text) 
+        || start_offset >= end_offset) return FALSE;
+
+    MyAtkText *self = (MyAtkText*)text;
+    GArray *selections = self->selections;
+    gint i;
+    for(i = 0; i < selections->len; i++)
+    {
+        if(g_array_index(selections, TextSelection, i).start_offset >= start_offset)
+        {
+            if(g_array_index(selections, TextSelection, i).start_offset < end_offset)
+                return FALSE;
+            break;
+        }
+    }    
+    TextSelection new_selection;
+    new_selection.start_offset = start_offset;
+    new_selection.end_offset = end_offset;
+    g_array_insert_val(selections, i, new_selection);
+    
+    g_signal_emit_by_name(text, "text-selection-changed");
+    return TRUE;
+}
+//********************************my_atk_text_set_selection*******************************
+gboolean my_atk_text_set_selection(AtkText *text,
+    gint selection_num, gint start_offset, gint end_offset)
+{
+    MyAtkText *self = (MyAtkText*)text;
+    GArray *selections = self->selections;
+    if(selection_num < 0 || selection_num >= selections->len) return FALSE;
+    
+    if((selection_num == 0 
+        || g_array_index(selections, TextSelection, selection_num - 1).end_offset <= start_offset)
+        && (selection_num == selections->len - 1
+        || g_array_index(selections, TextSelection, selection_num + 1).start_offset >= end_offset)
+        )
+    {
+        //Arrange of selections won't change
+        g_array_index(selections, TextSelection, selection_num).start_offset = 
+            start_offset;
+        g_array_index(selections, TextSelection, selection_num).end_offset =
+            end_offset;
+        g_signal_emit_by_name(text, "text-selection-changed");
+        return TRUE;
+    }
+    gint start_offset_old = 
+        g_array_index(selections, TextSelection, selection_num).start_offset;
+    gint end_offset_old = 
+        g_array_index(selections, TextSelection, selection_num).end_offset;
+    
+    my_atk_text_remove_selection(text, selection_num);
+    if(!my_atk_text_add_selection(text, start_offset, end_offset))
+    {
+        //fail when adding selection. Restore initial state.
+        my_atk_text_add_selection(text, start_offset_old, end_offset_old);
+        return FALSE;
+    }
+    g_signal_emit_by_name(text, "text-selection-changed");
+    return TRUE;
+
+}
+
+//************************************my_atk_text_get_caret_offset******************
+gint my_atk_text_get_caret_offset(AtkText *text)
+{
+    MyAtkText *self = (MyAtkText*)text;
+    return self->caret_offset;
+}
+//************************************my_atk_text_set_caret_offset******************
+gboolean my_atk_text_set_caret_offset(AtkText *text, gint offset)
+{
+    MyAtkText *self = (MyAtkText*)text;
+    //caret may be set just after the last character
+    if(offset < 0 || offset > my_atk_text_get_character_count(text))return FALSE;
+    self->caret_offset = offset;
+    g_signal_emit_by_name(self, "text-caret-moved", offset);
+    return TRUE;
+}
+
+//***********************my_atk_text_insert_text*******************************
+void my_atk_text_insert_text(AtkEditableText* text, const gchar* string,
+    gint length, gint *position)
+{
+    gint i;
+    MyAtkText* myAtkText = (MyAtkText*)text;
+    gchar *str = myAtkText->str;
+    gint strlen_old = my_strlen(str);
+    
+    if(string == NULL) return;
+    //correct length
+    for(i = 0; i < length; i ++)
+    {
+        if(string[i] == '\0') {length = i; break;}
+    }
+    
+    if(*position < 0 || *position > strlen_old || length <= 0 )return;
+    
+    
+    gchar *new_str = g_malloc(strlen_old + length + 1);
+    if(new_str == NULL)return;
+    
+    if(*position != 0) 
+        memcpy(new_str, str, (size_t)*position);
+    memcpy(new_str + *position, string, (size_t)length);
+    if(strlen_old != *position) 
+        memcpy(new_str + *position + length, str + *position,
+            (size_t)(strlen_old - *position));
+    new_str[strlen_old + length] = '\0';
+    
+    g_free(str);
+    myAtkText->str = new_str;
+    correct_selections_after_insert(myAtkText, *position, length);
+    correct_attributes_after_insert(myAtkText, *position, length);
+    correct_caret_after_insert(myAtkText, *position, length);
+    g_signal_emit_by_name(text, "text-changed::insert", *position, length);
+    g_signal_emit_by_name(text, "text-selection-changed");
+    g_signal_emit_by_name(text, "text-attributes-changed");
+    g_signal_emit_by_name(text, "text-caret-moved", myAtkText->caret_offset);
+    
+    (*position) += length;
+}
+//*************************my_atk_text_delete_text*******************
+void my_atk_text_delete_text(AtkEditableText* text, gint start_pos, gint end_pos)
+{
+    MyAtkText* myAtkText = (MyAtkText*)text;
+    gchar *str = myAtkText->str;
+    gint strlen_old = my_strlen(str);
+    
+    if(start_pos < 0 || end_pos > strlen_old || start_pos >= end_pos )return;
+    if(strlen_old != end_pos)
+        memmove(str + start_pos, str + end_pos, strlen_old - end_pos);
+    str[start_pos - end_pos + strlen_old] = '\0';
+    
+    correct_selections_after_delete(myAtkText, start_pos, end_pos - start_pos);
+    correct_attributes_after_delete(myAtkText, start_pos, end_pos - start_pos);
+    correct_caret_after_delete(myAtkText, start_pos, end_pos - start_pos);
+    g_signal_emit_by_name(text, "text-changed::delete", start_pos, end_pos - start_pos);
+    g_signal_emit_by_name(text, "text-selection-changed");
+    g_signal_emit_by_name(text, "text-attributes-changed");
+    g_signal_emit_by_name(text, "text-caret-moved", myAtkText->caret_offset);
+}
+//***********************my_atk_text_set_text_contents*************************
+void my_atk_text_set_text_contents(AtkEditableText* text, const gchar* string)
+{
+    my_atk_text_delete_text(text, 0, my_atk_text_get_character_count((AtkText*)text));
+    gint position = 0;
+    my_atk_text_insert_text(text, string, my_strlen(string), &position);
+}
+//**********************my_atk_text_copy_text***************************
+void my_atk_text_copy_text(AtkEditableText* text, gint start_pos, gint end_pos)
+{
+    MyAtkText* myAtkText = (MyAtkText*)text;
+    const gchar *str = myAtkText->str;
+    gint strlen_old = my_strlen(str);
+    if(start_pos < 0 || end_pos > strlen_old || start_pos >= end_pos )return;
+    
+    MyAtkTextClass *parent = MY_ATK_TEXT_GET_CLASS(text); 
+    g_free(parent->clipboard);
+    /*parent->clipboard = g_malloc(end_pos - start_pos + 1);
+    
+    strncpy(parent->clipboard, str + start_pos, end_pos - start_pos);
+    parent->clipboard[end_pos - start_pos] = '\0';*/
+    parent->clipboard = g_strndup(str + start_pos, end_pos - start_pos); 
+}
+//**********************my_atk_text_paste_text***************************
+void my_atk_text_paste_text(AtkEditableText *text, gint position)
+{
+    //NULL-clipboard process corretly
+    MyAtkTextClass* parent = MY_ATK_TEXT_GET_CLASS(text);
+    my_atk_text_insert_text(text, parent->clipboard, my_strlen(parent->clipboard), &position);
+}
+//**********************my_atk_text_cut_text***************************
+void my_atk_text_cut_text(AtkEditableText* text, gint start_pos, gint end_pos)
+{
+    my_atk_text_copy_text(text, start_pos, end_pos);
+    my_atk_text_delete_text(text, start_pos, end_pos);
+}
+//*********************my_atk_text_set_run_attributes************************
+gboolean my_atk_text_set_run_attributes(AtkEditableText* text, AtkAttributeSet* attrib_set,
+    gint start_offset, gint end_offset)
+{
+    MyAtkText* self = (MyAtkText*)text;
+    gint len = atk_text_get_character_count((AtkText*)text);
+    if(start_offset < 0 || start_offset >= end_offset || end_offset > len)
+        return FALSE;
+    GList *attributes = self->attributes;
+    GList *tmp = attributes;
+    
+    while(tmp != NULL)
+    {
+        Range *range = (Range*)tmp->data;
+        if(range->start < start_offset)
+        {
+            if(range->end <= end_offset)
+            {
+                if(range->end > start_offset) range->end = start_offset; 
+                tmp = tmp->next;
+                continue;
+            }
+            /*range->end > end_offset*/
+            Range* additional_range = range_new(end_offset, range->end);
+            additional_range->attributeSet = attribute_set_copy(range->attributeSet);
+            range->end = start_offset;
+            attributes = g_list_insert_before(attributes, tmp->next, additional_range);
+            tmp = tmp->next;
+            break;
+        }
+        else/*range->start >= start_offset*/
+        {
+            if(range->end <= end_offset)
+            {
+                GList *tmp1 = tmp->next;
+                attributes = g_list_remove_link(attributes, tmp);
+                tmp = tmp1;
+                continue;
+            }
+            /*range->end > end_offset*/
+            if(range->start < end_offset) range->start = end_offset;
+            break;
+        }
+    }
+    Range *new_range = range_new(start_offset, end_offset);
+    new_range->attributeSet = attribute_set_copy(attrib_set);
+    if(tmp == NULL)attributes = g_list_append(attributes, new_range);
+    else attributes = g_list_insert_before(attributes, tmp, new_range);
+    
+    self->attributes = attributes;
+    g_signal_emit_by_name(self, "text_attributes_changed");
+    return TRUE;
+}
+
+//others functions
+//sets default attributes
+void my_atk_text_set_default_attributes(MyAtkText* text, AtkAttributeSet *set)
+{
+    atk_attribute_set_free(text->default_attributes);
+    text->default_attributes = attribute_set_copy(set);
+    g_signal_emit_by_name(text, "text-attributes-changed");
+}
+
+void my_atk_text_print_run_attributes(MyAtkText *text)
+{
+    g_list_foreach(text->attributes, (GFunc)range_print, NULL);
+}
+void my_atk_text_print_default_attributes(MyAtkText *text)
+{
+    attribute_set_print(text->default_attributes);
+}
+//need for separate testing interfaces
+void auxiliary_atk_text_set_text_contents(MyAtkText* text, const gchar* string)
+{
+    my_atk_text_set_text_contents((AtkEditableText*)text, string);
+}
+void auxiliary_atk_text_set_run_attributes(MyAtkText* text, AtkAttributeSet* attrib_set,
+    gint start_offset, gint end_offset)
+{
+    my_atk_text_set_run_attributes((AtkEditableText*)text, attrib_set, start_offset, end_offset);
+}
+
+//initialize/finalize functions
+static void my_atk_text_instance_init(GTypeInstance *obj, gpointer g_class)
+{
+    MyAtkText *self = (MyAtkText*)obj;
+    
+    self->str = NULL;
+    self->attributes = NULL;
+    self->default_attributes = NULL;
+    text_bounds_init(&self->bounds);
+    
+    self->selections = g_array_new(FALSE, FALSE, sizeof(TextSelection));
+    
+    self->caret_offset = 0;
+}
+static void my_atk_text_instance_finalize(GObject* obj)
+{
+    MyAtkText *self = (MyAtkText*)obj;
+    g_free(self->str);
+    my_atk_text_free_run_attributes(self);
+    my_atk_text_free_default_attributes(self);
+    if(self->selections != NULL)g_array_free(self->selections, FALSE);
+}
+
+static void my_atk_text_class_init(gpointer g_class, gpointer class_data)
+{
+    GObjectClass* g_object_class = (GObjectClass*)g_class;
+    //GObject virtual table
+    g_object_class->finalize = my_atk_text_instance_finalize;
+    //Fills tables of symbols
+    table_symbols_init();
+    //initialize clipboard
+    ((MyAtkTextClass*)g_class)->clipboard = NULL;
+}
+//Because of static registration of type, finalization function will never been called
+//And glib prints warning if use it in registration.
+/*static void my_atk_text_class_finalize(gpointer g_class, gpointer class_data)
+{
+    MyAtkTextClass *self = (MyAtkTextClass*)g_class;
+    
+    g_free(self->clipboard);
+    self->clipboard = NULL; 
+}*/
+void my_atk_text_interface_init(gpointer g_iface, gpointer iface_data)
+{
+    AtkTextIface *klass = (AtkTextIface*)g_iface;
+    //"get_text"
+    klass->get_character_count = my_atk_text_get_character_count;
+    klass->get_text = my_atk_text_get_text;
+    klass->get_character_at_offset = my_atk_text_get_character_at_offset;
+    klass->get_text_after_offset = my_atk_text_get_text_after_offset;
+    klass->get_text_at_offset = my_atk_text_get_text_at_offset;
+    klass->get_text_before_offset = my_atk_text_get_text_before_offset;
+    //"attributes"
+    klass->get_run_attributes = my_atk_text_get_run_attributes;
+    klass->get_default_attributes = my_atk_text_get_default_attributes;
+    //"bounds"
+    klass->get_character_extents = my_atk_text_get_character_extents;
+    klass->get_range_extents = my_atk_text_get_range_extents;
+    klass->get_offset_at_point = my_atk_text_get_offset_at_point;
+    klass->get_bounded_ranges = my_atk_text_get_bounded_ranges; 
+    //"selection"
+    klass->get_n_selections = my_atk_text_get_n_selections;
+    klass->get_selection = my_atk_text_get_selection;
+    klass->remove_selection = my_atk_text_remove_selection;
+    klass->add_selection = my_atk_text_add_selection;
+    klass->set_selection = my_atk_text_set_selection;
+    //"caret"
+    klass->get_caret_offset = my_atk_text_get_caret_offset;
+    klass->set_caret_offset = my_atk_text_set_caret_offset;
+}
+
+static void my_atk_editable_text_interface_init(gpointer g_iface, gpointer iface_data)
+{
+    AtkEditableTextIface *klass = (AtkEditableTextIface*)g_iface;
+    
+    klass->set_text_contents = my_atk_text_set_text_contents;
+    klass->set_run_attributes = my_atk_text_set_run_attributes;
+    klass->copy_text =  my_atk_text_copy_text;
+    klass->insert_text =  my_atk_text_insert_text;
+    klass->paste_text = my_atk_text_paste_text;
+    klass->cut_text = my_atk_text_cut_text;
+    klass->delete_text = my_atk_text_delete_text;
+}
+GType my_atk_text_get_type()
+{
+    static GType type = 0;
+    if(type == 0)
+    {
+        static const GTypeInfo typeInfo = 
+        {
+            sizeof(MyAtkTextClass),
+            NULL,                       //base_init
+            NULL,                       //base_finalize
+            my_atk_text_class_init,     //class_init
+            NULL,                       //class_finalize
+            NULL,                       //class_data
+            sizeof(MyAtkText),
+            0,                          //n_preallocs
+            my_atk_text_instance_init   //instance_init
+        };
+
+        static const GInterfaceInfo AtkTextIface_info = 
+        {
+            my_atk_text_interface_init,         /* interface_init*/
+            NULL,                               /* interface_finalize*/
+            NULL                                /* interface_data */
+        };
+        static const GInterfaceInfo AtkEditableTextIface_info = 
+        {
+            my_atk_editable_text_interface_init,/* interface_init*/
+            NULL,                               /* interface_finalize*/
+            NULL                                /* interface_data */
+        };
+        type = g_type_register_static(MY_TYPE_ATK_OBJECT, "MyAtkText", &typeInfo, 0);
+        g_type_add_interface_static(type,
+            ATK_TYPE_TEXT,
+            &AtkTextIface_info);
+        
+        g_type_add_interface_static(type,
+            ATK_TYPE_EDITABLE_TEXT,
+            &AtkEditableTextIface_info);
+    }
+    return type;    
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-text.h pyatspi2/tests/dummyatk/my-atk-text.h
--- pyatspi2.old/tests/dummyatk/my-atk-text.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-text.h	2019-08-27 19:10:03.877588542 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MY_ATK_TEXT_H
+#define MY_ATK_TEXT_H
+/*
+ * MyAtkText: implements AtkText and AtkEditableText
+ */
+#include <atk/atk.h>
+
+#include "my-atk-object.h"
+	
+#define MY_TYPE_ATK_TEXT             (my_atk_text_get_type ())
+#define MY_ATK_TEXT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_ATK_TEXT, MyAtkText))
+#define MY_ATK_TEXT_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MY_TYPE_ATK_TEXT, MyAtkTextClass))
+#define MY_IS_ATK_TEXT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_ATK_TEXT))
+#define MY_IS_ATK_TEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MY_TYPE_ATK_TEXT))
+#define MY_ATK_TEXT_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MY_TYPE_ATK_TEXT, MyAtkTextClass))
+
+typedef struct _MyAtkText MyAtkText;
+typedef struct _MyAtkTextClass MyAtkTextClass;
+
+//Struct, describing bounds of one selection.
+typedef struct
+{
+    gint start_offset, end_offset;
+}TextSelection;
+//Struct, describing values, needed for determine extent of characters 
+typedef struct
+{
+    gint base_x, base_y;//coordinates of the top-left corner of text
+    gint pixels_above_line;
+    gint pixels_below_line;
+    gint size;//size of the character(height in pixels)
+    gint pixels_between_characters;//monoscaped font
+    gint width;//width of character
+}TextBounds; 
+
+struct _MyAtkText
+{
+    MyAtkObject parent;
+    
+    gchar* str;//string, containing text
+    GList* attributes;//running atributes
+    AtkAttributeSet *default_attributes;//default attributes
+    
+    TextBounds bounds;
+    
+    GArray* selections;
+    
+    gint caret_offset;
+};
+
+struct _MyAtkTextClass
+{
+    MyAtkObjectClass parent;
+    gchar* clipboard;
+};
+
+GType my_atk_text_get_type();
+
+void my_atk_text_interface_init(gpointer g_iface, gpointer iface_data);
+#endif /*MY_ATK_TEXT_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-value.c pyatspi2/tests/dummyatk/my-atk-value.c
--- pyatspi2.old/tests/dummyatk/my-atk-value.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-value.c	2019-08-27 19:10:03.877588542 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <atk/atk.h>
+#include <limits.h>
+
+#include "my-atk-object.h"
+#include "my-atk-value.h"
+
+//*************************implementation***********************
+//implementation of virtual functions
+//******************get_current_value*******************
+static void my_atk_value_get_current_value(AtkValue *obj, GValue *value)
+{
+    g_return_if_fail(MY_IS_ATK_VALUE(obj));
+    MyAtkValue* self = (MyAtkValue*)obj;
+    
+    g_value_init(value, G_TYPE_INT);
+    g_value_set_int(value, self->current);
+}
+//******************get_maximum_value*******************
+static void my_atk_value_get_maximum_value(AtkValue *obj, GValue *value)
+{
+    g_return_if_fail(MY_IS_ATK_VALUE(obj));
+    MyAtkValue* self = (MyAtkValue*)obj;
+    
+    g_value_init(value, G_TYPE_INT);
+    g_value_set_int(value, self->maximum);
+}
+//******************get_minimum_value*******************
+static void my_atk_value_get_minimum_value(AtkValue *obj, GValue *value)
+{
+    g_return_if_fail(MY_IS_ATK_VALUE(obj));
+    MyAtkValue* self = (MyAtkValue*)obj;
+    
+    g_value_init(value, G_TYPE_INT);
+    g_value_set_int(value, self->minimum);
+}
+//******************set_current_value*******************
+static gboolean my_atk_value_set_current_value(AtkValue *obj, const GValue *value)
+{
+    g_return_val_if_fail(MY_IS_ATK_VALUE(obj), FALSE);
+    MyAtkValue* self = (MyAtkValue*)obj;
+    
+    if(self->readonly) return FALSE;
+    
+    gint new_value = g_value_get_int(value);
+    if(new_value < self->minimum || new_value > self->maximum) return FALSE;
+    
+    self->current = new_value;
+    return TRUE;
+}
+
+//others
+MyAtkValue* my_atk_value_new(gint minimum, gint maximum, gint current)
+{
+    MyAtkValue* result = g_object_new(MY_TYPE_ATK_VALUE, NULL);
+    if(result == NULL) return NULL;
+    result->minimum = minimum;
+    result->maximum = maximum;
+    result->current = current;
+    
+    return result;
+}
+static void my_atk_value_instance_init(GTypeInstance *obj, gpointer g_class)
+{
+    MyAtkValue *self = (MyAtkValue*)obj;
+    
+    self->minimum = 0;
+    self->maximum = 0;
+    self->current = 0;
+    
+    self->readonly = FALSE;
+}
+static void my_atk_value_interface_init(gpointer g_iface, gpointer iface_data)
+{
+    AtkValueIface *klass = (AtkValueIface*)g_iface;
+    
+    klass->get_current_value = my_atk_value_get_current_value;
+    klass->get_minimum_value = my_atk_value_get_minimum_value;
+    klass->get_maximum_value = my_atk_value_get_maximum_value;
+    
+    klass->set_current_value = my_atk_value_set_current_value;
+}
+
+GType my_atk_value_get_type()
+{
+    static GType type = 0;
+    if(type == 0)
+    {
+        static const GTypeInfo typeInfo = 
+        {
+            sizeof(MyAtkValueClass),
+            NULL, //base_init
+            NULL, //base_finalize
+            NULL, //class_init
+            NULL, //class_finalize
+            NULL, //class_data
+            sizeof(MyAtkValue),
+            0, //n_preallocs
+            my_atk_value_instance_init //instance_init
+        };
+
+        static const GInterfaceInfo iface_info = 
+        {
+            my_atk_value_interface_init,        /* interface_init*/
+            NULL,                               /* interface_finalize*/
+            NULL                                /* interface_data */
+        };
+        type = g_type_register_static(MY_TYPE_ATK_OBJECT, "MyAtkValue", &typeInfo, 0);
+        g_type_add_interface_static(type,
+            ATK_TYPE_VALUE,
+            &iface_info);
+    }
+    return type;    
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/my-atk-value.h pyatspi2/tests/dummyatk/my-atk-value.h
--- pyatspi2.old/tests/dummyatk/my-atk-value.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/my-atk-value.h	2019-08-27 19:10:03.877588542 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MY_ATK_VALUE_H
+#define MY_ATK_VALUE_H
+/*
+ * MyAtkValue: derives AtkObject
+ * and implements AtkValue
+ */
+#include <atk/atk.h>
+
+#define MY_TYPE_ATK_VALUE             (my_atk_value_get_type ())
+#define MY_ATK_VALUE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_ATK_VALUE, MyAtkValue))
+#define MY_ATK_VALUE_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MY_TYPE_ATK_VALUE, MyAtkValueClass))
+#define MY_IS_ATK_VALUE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_ATK_VALUE))
+#define MY_IS_ATK_VALUE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MY_TYPE_ATK_VALUE))
+#define MY_ATK_VALUE_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MY_TYPE_ATK_VALUE, MyAtkValueClass))
+
+typedef struct _MyAtkValue MyAtkValue;
+typedef struct _MyAtkValueClass MyAtkValueClass;
+
+struct _MyAtkValue
+{
+    MyAtkObject parent;
+    
+    gint minimum, maximum, current;
+    gboolean readonly;
+};
+
+struct _MyAtkValueClass
+{
+    MyAtkObjectClass parent;
+};
+
+MyAtkValue* my_atk_value_new(gint minimum, gint maximium, gint current);
+GType my_atk_value_get_type();
+#endif /*MY_ATK_VALUE_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/resources_storage.c pyatspi2/tests/dummyatk/resources_storage.c
--- pyatspi2.old/tests/dummyatk/resources_storage.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/resources_storage.c	2019-08-27 19:10:03.877588542 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <atk/atk.h>
+
+GHashTable* resources = NULL;
+
+void resource_storage_init()
+{
+    if(resources == NULL)
+    resources = g_hash_table_new_full(g_str_hash, g_str_equal,
+        (GDestroyNotify)g_free, (GDestroyNotify)g_object_unref);
+}
+
+void resource_storage_free()
+{
+    if(resources == NULL) return;
+    g_hash_table_destroy(resources);
+    resources = NULL;
+}
+
+void resource_storage_add(const gchar* name, AtkObject* resource)
+{
+    if(resources == NULL) return;
+    g_hash_table_insert(resources, g_strdup(name), g_object_ref(resource));
+}
+
+AtkObject* resource_storage_get(const gchar* name)
+{
+    if(resources == NULL) return NULL;
+    return g_hash_table_lookup(resources, name);
+}
+void resources_storage_remove(const gchar* name)
+{
+    if(resources == NULL) return;
+    g_hash_table_remove(resources, name);
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/resources_storage.h pyatspi2/tests/dummyatk/resources_storage.h
--- pyatspi2.old/tests/dummyatk/resources_storage.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/resources_storage.h	2019-08-27 19:10:03.877588542 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RESOURCES_STORAGE_H
+#define RESOURCES_STORAGE_H
+
+#include <glib.h>
+
+void resource_storage_init();
+
+void resource_storage_free();
+
+void resource_storage_add(const gchar* name, AtkObject* resource);
+
+AtkObject* resource_storage_get(const gchar* name);
+
+void resources_storage_remove(const gchar* name);
+
+#endif /*RESOURCES_STORAGE_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/useful_functions.c pyatspi2/tests/dummyatk/useful_functions.c
--- pyatspi2.old/tests/dummyatk/useful_functions.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/useful_functions.c	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h>
+#include <glib.h>
+/*
+ * Functions and macros widely used in the tests.
+ */
+ 
+//same as strcmp() == 0 but works properly for NULL pointers
+gboolean my_strcmp(const gchar* str1, const gchar* str2)
+{
+    if(str1 == str2) return TRUE;
+    if(str1 == NULL || str2 == NULL) return FALSE;
+    
+    return strcmp(str1,str2) == 0;
+}
+//same as strlen but works properly for NULL pointer and returns gint instead of guint
+gint my_strlen(const gchar* str)
+{
+    if(str == NULL)return 0;
+    return (gint)strlen(str);
+}
+//same as strncmp() == 0 but works properly for NULL pointers
+gboolean my_strncmp(const gchar* str1, const gchar* str2, gint n)
+{
+    if(n <= 0)return TRUE;
+    if(str1 == str2)return TRUE;
+    if(str1 == NULL || str2 == NULL)return FALSE;
+
+    return strncmp(str1, str2, n) == 0;
+}
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/useful_functions.h pyatspi2/tests/dummyatk/useful_functions.h
--- pyatspi2.old/tests/dummyatk/useful_functions.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/useful_functions.h	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef USEFUL_FUNCTIONS_H
+#define USEFUL_FUNCTIONS_H
+/*
+ * Functions and macros widely used in the tests.
+ */
+ 
+//macro for creating objects in startup section
+#define OBJECT_NEW(obj, type, type_str) obj = g_object_new(type,NULL);\
+    if(obj == NULL)\
+    {\
+        INIT_FAILED("Cannot create instance of type" type_str ".\n");\
+    }
+//macro for destroying object 
+#define OBJECT_UNREF(obj) if(obj != NULL)\
+    {\
+        g_object_unref((gpointer)obj);\
+    }
+//for testing signals
+#define HANDLER_DISCONNECT(obj, h) if((h) != 0)\
+	{\
+		g_signal_handler_disconnect(obj, h);\
+	}
+
+gboolean my_strcmp(const gchar* str1, const gchar* str2);
+
+gint my_strlen(const gchar* str);
+
+gboolean my_strncmp(const gchar* str1, const gchar* str2, gint n);
+
+#endif /*USEFUL_FUNCTIONS_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/user_marshal.c pyatspi2/tests/dummyatk/user_marshal.c
--- pyatspi2.old/tests/dummyatk/user_marshal.c	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/user_marshal.c	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include	<glib-object.h>
+
+/* INT:BOXED (marshal.list:1) */
+void
+g_cclosure_user_marshal_INT__BOXED (GClosure     *closure,
+                                    GValue       *return_value,
+                                    guint         n_param_values,
+                                    const GValue *param_values,
+                                    gpointer      invocation_hint,
+                                    gpointer      marshal_data)
+{
+  typedef gint (*GMarshalFunc_INT__BOXED) (gpointer     data1,
+                                           gpointer     arg_1,
+                                           gpointer     data2);
+  register GMarshalFunc_INT__BOXED callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gint v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_INT__BOXED) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_boxed (param_values + 1),
+                       data2);
+
+  g_value_set_int (return_value, v_return);
+}
+
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/dummyatk/user_marshal.h pyatspi2/tests/dummyatk/user_marshal.h
--- pyatspi2.old/tests/dummyatk/user_marshal.h	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/dummyatk/user_marshal.h	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef USER_MARSHAL_H
+#define USER_MARSHAL_H
+
+#include	<glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+void
+g_cclosure_user_marshal_INT__BOXED (GClosure     *closure,
+                                    GValue       *return_value,
+                                    guint         n_param_values,
+                                    const GValue *param_values,
+                                    gpointer      invocation_hint,
+                                    gpointer      marshal_data);
+
+#endif /*USER_MARSHAL_H*/
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/Makefile.am pyatspi2/tests/Makefile.am
--- pyatspi2.old/tests/Makefile.am	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/Makefile.am	2019-08-26 23:04:09.541759565 +0200
@@ -0,0 +1,11 @@
+SUBDIRS = dummyatk apps data pyatspi
+
+#TESTS=testrunner.py
+TESTS_ENVIRONMENT = PYTHONPATH=$(abs_top_srcdir)/python					\
+		    ATSPI_INTROSPECTION_PATH=$(top_srcdir)/xml/introspection		\
+		    TEST_DATA_DIRECTORY=$(abs_top_srcdir)/tests/data			\
+		    TEST_ATSPI_LIBRARY=$(abs_top_srcdir)/atk-adaptor/.libs/libspiatk.so	\
+		    TEST_MODULES_DIRECTORY=$(abs_top_srcdir)/tests/apps/.libs		\
+		    TEST_APPLICATION=$(abs_top_srcdir)/tests/apps/test-application
+
+CLEANFILES = *.pyc
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/accessibletest.py pyatspi2/tests/pyatspi/accessibletest.py
--- pyatspi2.old/tests/pyatspi/accessibletest.py	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/accessibletest.py	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,248 @@
+#
+# Copyright 2008 Codethink Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+
+import dbus
+from gi.repository import GObject
+import os.path
+
+from xml.dom import minidom
+import os
+
+from pasytest import PasyTest as _PasyTest
+
+import pyatspi
+from pyatspi import StateSet
+
+st = [pyatspi.STATE_MULTI_LINE,
+      pyatspi.STATE_MODAL,
+      pyatspi.STATE_INDETERMINATE,
+      pyatspi.STATE_SUPPORTS_AUTOCOMPLETION,
+      pyatspi.STATE_VERTICAL,]
+
+def _createNode(accessible, parentElement):
+	e = minidom.Element("accessible")
+
+	e.attributes["name"] = accessible.name
+	e.attributes["role"] = str(int(accessible.getRole()))
+	e.attributes["description"] = accessible.description
+
+	for i in range(0, accessible.childCount):
+		_createNode(accessible.getChildAtIndex(i), e)
+
+	parentElement.appendChild(e)
+
+class AccessibleTest(_PasyTest):
+
+	__tests__ = ["setup",
+		     "test_name",
+		     "test_getChildAtIndex",
+		     "test_isEqual",
+		     "test_getApplication",
+		     "test_getAttributes",
+		     "test_parent",
+		     "test_getIndexInParent",
+		     "test_getLocalizedRoleName",
+		     "test_getRelationSet",
+		     "test_getRole",
+		     "test_getRoleName",
+		     "test_getState",
+		     "test_childCount",
+		     "test_description",
+		     "test_tree",
+		     "test_null_interface",
+		     "teardown",
+		     ]
+
+	def __init__(self, bus, path):
+		_PasyTest.__init__(self, "Accessible", False)
+		self._bus = bus
+		self._path = path
+
+	def setup(self, test):
+		self._registry = pyatspi.Registry()
+		self._desktop = self._registry.getDesktop(0)
+                self._root = pyatspi.findDescendant (self._desktop, lambda x: x.name == "atspi-test-main" and x.getRole() == pyatspi.ROLE_WINDOW)
+
+	def test_name(self, test):
+		root = self._root
+		test.assertEqual(root.name, "atspi-test-main", "Expected name - \"main\". Recieved - \"%s\"" % (root.name,))
+
+	def test_getChildAtIndex(self, test):
+		root = self._root
+		a = root.getChildAtIndex(0)
+		test.assertEqual(a.name, "gnome-settings-daemon",
+					 "Expected name - \"gnome-settings-daemon\". Recieved - \"%s\"" % (a.name,))
+		b = root.getChildAtIndex(1)
+		test.assertEqual(b.name, "gnome-panel",
+					 "Expected name - \"gnome-panel\". Recieved - \"%s\"" % (b.name,))
+		c = root.getChildAtIndex(2)
+		test.assertEqual(c.name, "nautilus",
+					 "Expected name - \"nautilus\". Recieved - \"%s\"" % (c.name,))
+		
+	def test_isEqual(self, test):
+		root = self._root
+
+		a = root.getChildAtIndex(1)
+		if not a.isEqual(a):
+			test.fail("Same accessible found unequal to self")
+
+		b = root.getChildAtIndex(1)
+		if not a.isEqual(b):
+			test.fail("Similar accessibles found unequal")
+		if not b.isEqual(a):
+			test.fail("Similar accessibles found unequal")
+
+		c = root.getChildAtIndex(2)
+		if c.isEqual(a):
+			test.fail("Different accessibles found equal")
+		if a.isEqual(c):
+			test.fail("Different accessibles found equal")
+
+	def test_getApplication(self, test):
+		root = self._root
+		application = root.getApplication()
+		if not root.isEqual(application):
+			test.fail("Root accessible does not provide itself as its Application")
+
+		a = root.getChildAtIndex(1)
+		application = a.getApplication()
+		if not root.isEqual(application):
+			test.fail("Child accessible does not provide the root as its Application")
+
+
+	def test_getAttributes(self, test):
+		root = self._root
+		attr = root.getAttributes()
+		res = ["foo:bar", "baz:qux", "quux:corge"]
+                attr.sort()
+                res.sort()
+		test.assertEqual(attr, res, "Attributes expected %s, recieved %s" % (res, attr))
+
+	def test_parent(self, test):
+		root = self._root
+
+		a = root.getChildAtIndex(1)
+		pa = a.parent
+		if not root.isEqual(pa):
+			test.fail("Child does not correctly report its parent")
+
+	def test_getIndexInParent(self, test):
+		root = self._root
+
+		for i in range(0, root.childCount):
+			child = root.getChildAtIndex(i)
+			test.assertEqual(i, child.getIndexInParent(), "Childs index in parent reported incorrectly")
+
+	def test_getLocalizedRoleName(self, test):
+		root = self._root
+
+		ans = "window"
+		res = root.getLocalizedRoleName()
+		test.assertEqual(ans, res,
+				 "Expected LocalizedRoleName - \"%s\". Recieved - \"%s\"" % (ans, res,))
+
+		a = root.getChildAtIndex(1)
+		a = a.getChildAtIndex(0)
+		ans = "html container"
+		res = a.getLocalizedRoleName()
+		test.assertEqual(ans, res,
+				 "Expected LocalizedRoleName - \"%s\". Recieved - \"%s\"" % (ans, res,))
+
+	def test_getRelationSet(self, test):
+		root = self._root
+		# Complete test of Relation interface is separate
+		rset = root.getRelationSet()
+
+	def test_getRole(self, test):
+		root = self._root
+		test.assertEqual(root.getRole(), 69,
+				 "Expected role - \"69\". Recieved - \"%d\"" % (int(root.getRole()),))
+
+	def test_getRoleName(self, test):
+		root = self._root
+
+		ans = "window"
+		res = root.getRoleName()
+		test.assertEqual(ans, res,
+				 "Expected roleName - \"%s\". Recieved - \"%s\"" % (ans, res,))
+
+		a = root.getChildAtIndex(1)
+		a = a.getChildAtIndex(0)
+		ans = "html container"
+		res = a.getRoleName()
+		test.assertEqual(ans, res,
+				 "Expected roleName - \"%s\". Recieved - \"%s\"" % (ans, res,))
+
+	def test_getState(self, test):
+		root = self._root
+		state = root.getState()
+		res = StateSet(*st)
+		if not res.equals(state):
+			test.fail("States not reported correctly")
+
+	def test_childCount(self, test):
+		root = self._root
+		test.assertEqual(root.childCount, 11,
+				 "Expected role - \"11\". Recieved - \"%d\"" % (root.childCount,))
+
+	def test_description(self, test):
+		root = self._root
+		description = "The main accessible object, root of the accessible tree"
+		test.assertEqual(root.description, description,
+				 "Expected description - \"%s\". Recieved - \"%s\"" % (description, root.description,))
+
+	def test_tree(self, test):
+		"""
+		This is a mild stress test for the 
+		methods:
+
+		getChildAtIndex
+		
+		And the attributes:
+
+		name
+		description
+
+		It checks a tree of these values is correctly
+		passed from Application to AT.
+		"""
+		root = self._root
+
+		doc = minidom.Document()
+		_createNode(root, doc)
+		answer = doc.toprettyxml()
+
+
+		correct = os.path.join(os.environ["TEST_DATA_DIRECTORY"],
+					"accessible-test-results.xml")
+		file = open(correct)
+		cstring = file.read()
+		
+		test.assertEqual(answer, cstring, "Object tree not passed correctly")
+
+	def test_null_interface(self, test):
+		root = self._root
+		try:
+			text = root.queryText()
+		except NotImplementedError:
+			return
+		test.fail ("Should throw NotImplementedError")
+
+	def teardown(self, test):
+		pass
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/actiontest.py pyatspi2/tests/pyatspi/actiontest.py
--- pyatspi2.old/tests/pyatspi/actiontest.py	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/actiontest.py	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,101 @@
+#
+# Copyright 2008 Codethink Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+
+import dbus
+from gi.repository import GObject
+import os.path
+
+from xml.dom import minidom
+import os
+
+from pasytest import PasyTest as _PasyTest
+
+import pyatspi
+
+class ActionTest(_PasyTest):
+
+	__tests__ = ["setup",
+		     "test_nActions",
+		     "test_getDescription",
+		     "test_getName",
+		     "test_doAction",
+		     "test_getKeyBinding",
+		     "teardown",
+		     ]
+
+	def __init__(self, bus, path):
+		_PasyTest.__init__(self, "Action", False)
+		self._bus = bus
+		self._path = path
+
+	def setup(self, test):
+		self._registry = pyatspi.Registry()
+		import time
+		self._desktop = self._registry.getDesktop(0)
+		print "--desktop len", len(self._desktop)
+		for i in self._desktop:
+			try:
+				print "-- object",i,i.getRole()
+			except:
+				pass
+                self._root = pyatspi.findDescendant (self._desktop, lambda x: x.name == "atspi-test-main" and x.getRole() == pyatspi.ROLE_APPLICATION)
+		print "--root", self._root
+
+	def test_nActions(self, test):
+		root = self._root
+		root = root.queryAction()
+		nact = root.nActions
+		test.assertEqual(nact, 10, "nActions expected %d, recieved %d" % (10, nact))
+
+	def test_getName(self, test):
+		root = self._root
+		root = root.queryAction()
+		name = root.getName(0)
+		test.assertEqual(name, "First action", "Name expected %s, recieved %s" % ("First action", name))
+		name = root.getName(1)
+		test.assertEqual(name, "Action", "Name expected %s, recieved %s" % ("Action", name))
+
+	def test_getDescription(self, test):
+		root = self._root
+		root = root.queryAction()
+		description = root.getDescription(0)
+		expected = "First action performed"
+		test.assertEqual(description, expected, "Description expected %s, recieved %s" % (expected, description))
+		description = root.getDescription(1)
+		expected = "Description of action"
+		test.assertEqual(description, expected, "Description expected %s, recieved %s" % (expected, description))
+
+	def test_doAction(self, test):
+		root = self._root
+		root = root.queryAction()
+		#TODO have event emitted to check action has been performed
+		for i in range(0, root.nActions):
+			root.doAction(i)
+
+	def test_getKeyBinding(self, test):
+		root = self._root
+		root = root.queryAction()
+		for i in range(0, root.nActions):
+			keybinding = root.getKeyBinding(i)
+			expected = "%s" % (i,)
+			test.assertEqual(keybinding, expected,
+					 "Keybinding expected %s, recieved %s" % (expected, keybinding))
+
+	def teardown(self, test):
+		pass
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/collectiontest.py pyatspi2/tests/pyatspi/collectiontest.py
--- pyatspi2.old/tests/pyatspi/collectiontest.py	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/collectiontest.py	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,205 @@
+#
+# Copyright 2009 Novell, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+
+import dbus
+from gi.repository import GObject
+import os.path
+
+from xml.dom import minidom
+import os
+
+from pasytest import PasyTest as _PasyTest
+
+import pyatspi
+from pyatspi import StateSet
+
+st = [pyatspi.STATE_MULTI_LINE,
+      pyatspi.STATE_MODAL,
+      pyatspi.STATE_INDETERMINATE,
+      pyatspi.STATE_SUPPORTS_AUTOCOMPLETION,
+      pyatspi.STATE_VERTICAL,]
+
+def _createNode(accessible, parentElement):
+        e = minidom.Element("accessible")
+
+        e.attributes["name"] = accessible.name
+        e.attributes["role"] = str(int(accessible.getRole()))
+        e.attributes["description"] = accessible.description
+
+        for i in range(0, accessible.childCount):
+                _createNode(accessible.getChildAtIndex(i), e)
+
+        parentElement.appendChild(e)
+
+class AccessibleTest(_PasyTest):
+
+        __tests__ = ["setup",
+                     "test_basic",
+                     "test_match_any",
+                     "test_role",
+                     "teardown",
+                     ]
+
+        def __init__(self, bus, path):
+                _PasyTest.__init__(self, "Collection", False)
+                self._bus = bus
+                self._path = path
+
+
+        def setup(self, test):
+                self._registry = pyatspi.Registry()
+                print self._path
+                self._desktop = self._registry.getDesktop(0)
+                self._root = pyatspi.findDescendant (self._desktop, lambda x: x.name == "atspi-test-main" and x.getRole() == pyatspi.ROLE_WINDOW)
+
+        def assertObjects(self,test,obj,vars,msg):
+                test.assertEqual(len(obj), len(vars) / 2, msg + " length")
+                for i in range(0, len(vars), 2):
+                        test.assertEqual (vars[i], obj[i/2].name, msg + "name" + "#" + str(i/2))
+                        test.assertEqual(vars[i+1], obj[i/2].getRole(), msg + " role" + "#" + str(i/2))
+
+	# Used to help add new tests
+        def printAsserts(self,obj,msg):
+                print "\t\tself.assertObjects(test,ret,("
+                for i in range(0,len(obj)):
+                        print "\t\t\t\"" + obj[i].name + "\", " + str(obj[i].getRole()) + ","
+                print "\t\t), \"", msg, "\")"
+
+        def test_basic(self, test):
+                collection = self._root.queryCollection()
+                stateSet = pyatspi.StateSet()
+                rule = collection.createMatchRule (stateSet.raw(),
+                        collection.MATCH_NONE,
+                [],     # attributes
+                        collection.MATCH_NONE,
+                [],     # role
+                        collection.MATCH_NONE,
+                "",     # interfaces
+                        collection.MATCH_NONE,
+                        False)
+
+                ret = collection.getMatches (rule, collection.SORT_ORDER_CANONICAL, 5, True)
+                self.assertObjects(test,ret,(
+                        "gnome-settings-daemon", 79 ,
+                        "gnome-panel", 79 ,
+                        "Bottom Expanded Edge Panel", 25 ,
+                        "Top Expanded Edge Panel", 25 ,
+                        "nautilus", 79 ,
+                ), " 1 ")
+
+                ret = collection.getMatches (rule, collection.SORT_ORDER_REVERSE_CANONICAL, 5, True)
+                self.assertObjects(test,ret,(
+                        "nautilus", 79,
+                        "Top Expanded Edge Panel", 25,
+                        "Bottom Expanded Edge Panel", 25,
+                        "gnome-panel", 79,
+                        "gnome-settings-daemon", 79,
+                ), " reverse canonical ")
+
+                obj=ret[2]
+                ret = collection.getMatchesTo (obj, rule, collection.SORT_ORDER_REVERSE_CANONICAL, collection.TREE_INORDER, True, 5, True)
+		print "--ret:", len(ret)
+                self.assertObjects(test,ret,(
+                        "gnome-settings-daemon", 79,
+                        "gnome-panel", 79,
+                ), " getMatchesTo ")
+                ret = collection.getMatchesTo (obj, rule, collection.SORT_ORDER_REVERSE_CANONICAL, collection.TREE_INORDER, True, 1, True)
+                self.assertObjects(test,ret,(
+                        "gnome-panel", 79,
+                ), " getMatchesTo w/count=1")
+                ret = collection.getMatchesFrom (obj, rule, collection.SORT_ORDER_REVERSE_CANONICAL, collection.TREE_INORDER, 5, True)
+                self.assertObjects(test,ret,(
+                        "tracker-applet", 79,
+                        "metacity", 79,
+                        "Desktop", 25,
+                        "nautilus", 79,
+                        "Top Expanded Edge Panel", 25,
+                ), " getMatchesFrom ")
+                obj = self._root.getChildAtIndex(1)
+                ret = collection.getMatchesFrom (obj, rule, collection.SORT_ORDER_CANONICAL, collection.TREE_RESTRICT_CHILDREN, 5, True)
+                self.assertObjects(test,ret,(
+                        "Top Expanded Edge Panel", 25,
+                ), " Restrict Children ")
+
+        def test_match_any(self, test):
+                collection = self._root.queryCollection()
+                stateSet = pyatspi.StateSet()
+                rule = collection.createMatchRule (stateSet.raw(),
+                        collection.MATCH_ANY,
+                [],     # attributes
+                        collection.MATCH_ANY,
+                [],     # role
+                        collection.MATCH_ANY,
+                "",     # interfaces
+                        collection.MATCH_NONE,
+                        False)
+
+                ret = collection.getMatches (rule, collection.SORT_ORDER_CANONICAL, 5, True)
+                self.assertObjects(test,ret,(
+                        "gnome-settings-daemon", 79 ,
+                        "gnome-panel", 79 ,
+                        "Bottom Expanded Edge Panel", 25 ,
+                        "Top Expanded Edge Panel", 25 ,
+                        "nautilus", 79 ,
+                ), " 1 ")
+
+        def test_role(self, test):
+                collection = self._root.queryCollection()
+                stateSet = pyatspi.StateSet()
+
+                rule = collection.createMatchRule (stateSet.raw(),
+                        collection.MATCH_NONE,
+                [],     # attributes
+                        collection.MATCH_NONE,
+                [pyatspi.ROLE_RADIO_MENU_ITEM],
+                        collection.MATCH_ANY,
+                "",     # interfaces
+                        collection.MATCH_NONE,
+                        False)
+
+                ret = collection.getMatches (rule, collection.SORT_ORDER_CANONICAL, 5, True)
+                self.assertObjects(test,ret,(
+                        "Activity Indicator", 45,
+                        "Back", 45,
+                        "Forward", 45,
+                        "", 45,
+                        "Reload", 45,
+                ), " role ")
+
+                rule = collection.createMatchRule (stateSet.raw(),
+                        collection.MATCH_NONE,
+                [],     # attributes
+                        collection.MATCH_NONE,
+                [pyatspi.ROLE_ENTRY, pyatspi.ROLE_HTML_CONTAINER],
+                        collection.MATCH_ANY,
+                "",     # interfaces
+                        collection.MATCH_NONE,
+                        False)
+
+                ret = collection.getMatches (rule, collection.SORT_ORDER_CANONICAL, 5, True)
+                self.assertObjects(test,ret,(
+                        "gnome-settings-daemon", 79,
+                        "gnome-panel", 79,
+                        "Bottom Expanded Edge Panel", 25,
+                        "Top Expanded Edge Panel", 25,
+                        "nautilus", 79,
+                        ), " role #2")
+
+        def teardown(self, test):
+                pass
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/componenttest.py pyatspi2/tests/pyatspi/componenttest.py
--- pyatspi2.old/tests/pyatspi/componenttest.py	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/componenttest.py	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,164 @@
+#
+# Copyright 2008 Codethink Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+
+import dbus
+from gi.repository import GObject
+import os.path
+
+from xml.dom import minidom
+import os
+
+from pasytest import PasyTest as _PasyTest
+
+import pyatspi
+from pyatspi.Accessibility import Component
+from pyatspi.utils import BoundingBox
+
+ATSPI_LAYER_WIDGET = 3
+ATSPI_LAYER_MDI = 4
+ATSPI_LAYER_WINDOW = 7
+
+extents_expected = [(0,0,30,20), (40,30,30,40), (0,0,70,70)]
+sizes_expected = [(30,20), (30,40), (70,70)]
+positions_expected = [(0,0), (40,30), (0,0)]
+layers_expected = [ATSPI_LAYER_WINDOW, ATSPI_LAYER_WIDGET, ATSPI_LAYER_MDI]
+zorders_expected = [-100, 100]
+
+class ComponentTest(_PasyTest):
+
+	__tests__ = ["setup",
+		     "test_contains",
+		     "test_getAccessibleAtPoint",
+		     "test_getExtents",
+		     "test_getPosition",
+		     "test_getSize",
+		     "test_getLayer",
+		     "test_getMDIZOrder",
+		     "test_grabFocus",
+		     "test_registerFocusHandler",
+		     "test_deregisterFocusHandler",
+		     "test_getAlpha",
+		     "teardown",
+		     ]
+
+	def __init__(self, bus, path):
+		_PasyTest.__init__(self, "Component", False)
+		self._bus = bus
+		self._path = path
+
+	def setup(self, test):
+		self._registry = pyatspi.Registry()
+		self._desktop = self._registry.getDesktop(0)
+                self._root = pyatspi.findDescendant (self._desktop, lambda x: x.name == "atspi-test-main" and x.getRole() == pyatspi.ROLE_APPLICATION)
+
+	def test_contains(self, test):
+		pass
+
+	def test_getAccessibleAtPoint(self, test):
+		pass
+
+	def test_getExtents(self, test):
+		root = self._root
+		one = root.getChildAtIndex(0)
+		two = root.getChildAtIndex(1)
+
+		comps = [one.queryComponent(),
+			 two.queryComponent(),
+			 root.queryComponent(),]
+ 
+		for expected, comp in zip(extents_expected, comps):
+			extents = comp.getExtents(0)
+			test.assertEqual(extents, BoundingBox(*expected), 
+					 "Extents not correct. Expected (%d, %d, %d, %d), Recieved (%d, %d, %d, %d)"
+					 % (expected[0], expected[1], expected[2], expected[3], 
+						extents[0], extents[1], extents[2], extents[3]))
+
+	def test_getPosition(self, test):
+		root = self._root
+		one = root.getChildAtIndex(0)
+		two = root.getChildAtIndex(1)
+
+		comps = [one.queryComponent(),
+			 two.queryComponent(),
+			 root.queryComponent(),]
+ 
+		for expected, comp in zip(positions_expected, comps):
+			position = comp.getPosition(0)
+			test.assertEqual(position, expected, 
+					 "Position not correct. Expected (%d, %d) Recieved (%d, %d)"
+					 % (expected[0], expected[1], position[0], position[1]))
+
+	def test_getSize(self, test):
+		root = self._root
+		one = root.getChildAtIndex(0)
+		two = root.getChildAtIndex(1)
+
+		comps = [one.queryComponent(),
+			 two.queryComponent(),
+			 root.queryComponent(),]
+ 
+		for expected, comp in zip(sizes_expected, comps):
+			size = comp.getSize()
+			test.assertEqual(size, expected, 
+					 "Size not correct. Expected (%d, %d) Recieved (%d, %d)"
+					 % (expected[0], expected[1], size[0], size[1]))
+
+	def test_getLayer(self, test):
+		root = self._root
+		one = root.getChildAtIndex(0)
+		two = root.getChildAtIndex(1)
+
+		comps = [one.queryComponent(),
+			 two.queryComponent(),
+			 root.queryComponent(),]
+ 
+		for expected, comp in zip(layers_expected, comps):
+			layer = comp.getLayer()
+			test.assertEqual(layer, expected, 
+					 "Layer not correct. Expected %d, Recieved %d"
+					 % (int(layer), int(expected)))
+
+	def test_getMDIZOrder(self, test):
+		root = self._root
+		one = root.getChildAtIndex(0)
+		two = root.getChildAtIndex(1)
+
+		comps = [two.queryComponent(),
+			 root.queryComponent(),]
+ 
+		for expected, comp in zip(zorders_expected, comps):
+			mdizo = comp.getMDIZOrder()
+			test.assertEqual(mdizo, expected, 
+					 "ZOrder not correct. Expected %d, Recieved %d"
+					 % (expected, mdizo))
+
+	def test_grabFocus(self, test):
+		pass
+
+	def test_registerFocusHandler(self, test):
+		pass
+
+	def test_deregisterFocusHandler(self, test):
+		pass
+
+	def test_getAlpha(self, test):
+		pass
+
+	def teardown(self, test):
+		pass
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/desktoptest.py pyatspi2/tests/pyatspi/desktoptest.py
--- pyatspi2.old/tests/pyatspi/desktoptest.py	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/desktoptest.py	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,203 @@
+#
+# Copyright 2008 Codethink Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+
+import dbus
+from gi.repository import GObject
+import os.path
+
+from xml.dom import minidom
+import os
+
+from pasytest import PasyTest as _PasyTest
+
+import pyatspi
+
+class DesktopTest(_PasyTest):
+
+	__tests__ = ["setup",
+		     "test_name",
+		     "test_getChildAtIndex",
+		     "test_isEqual",
+		     "test_getApplication",
+		     "test_getAttributes",
+		     "test_parent",
+		     "test_getIndexInParent",
+		     "test_getLocalizedRoleName",
+		     "test_getRelationSet",
+		     "test_getRole",
+		     "test_getRoleName",
+		     "test_getState",
+		     "test_childCount",
+		     "test_description",
+		     "test_contains",
+		     "test_getAccessibleAtPoint",
+		     "test_getExtents",
+		     "test_getPosition",
+		     "test_getSize",
+		     "test_getLayer",
+		     "test_getMDIZOrder",
+		     "test_grabFocus",
+		     "test_registerFocusHandler",
+		     "test_deregisterFocusHandler",
+		     "test_getAlpha",
+		     "teardown",
+		     ]
+
+	def __init__(self, bus, path):
+		_PasyTest.__init__(self, "Desktop", False)
+		self._bus = bus
+		self._path = path
+
+	def setup(self, test):
+		self._registry = pyatspi.Registry()
+		self._desktop = self._registry.getDesktop(0)
+
+	def test_name(self, test):
+		name = self._desktop.name
+		test.assertEqual(name, "main", "Expected name - \"main\". Recieved - \"%s\"" % (name,))
+
+	def test_getChildAtIndex(self, test):
+		root = self._desktop.getChildAtIndex(0)
+		test.assertEqual(root.name, "main",
+					 "Expected name - \"main\". Recieved - \"%s\"" % (root.name,))
+		
+	def test_isEqual(self, test):
+		if not self._desktop.isEqual(self._desktop):
+			test.fail("Same accessible found unequal to self")
+
+		root = self._desktop.getChildAtIndex(0)
+		if root.isEqual(self._desktop):
+			test.fail("Different accessibles found equal")
+		if self._desktop.isEqual(root):
+			test.fail("Different accessibles found equal")
+
+	def test_getApplication(self, test):
+		test.assertEqual(self._desktop.getApplication(), None,
+				"Expected application - \"None\". Recieved - \"%s\"" % (self._desktop.getApplication(),))
+
+	def test_getAttributes(self, test):
+		test.assertEqual(self._desktop.getAttributes(), [],
+				"Expected attributes - \"[]\". Recieved - \"%s\"" % (self._desktop.getAttributes(),))
+
+	def test_parent(self, test):
+		test.assertEqual(self._desktop.parent, None,
+				"Expected parent - \"None\". Recieved - \"%s\"" % (self._desktop.parent,))
+
+	def test_getIndexInParent(self, test):
+		test.assertEqual(self._desktop.getIndexInParent(), -1,
+				"Expected index - \"-1\". Recieved - \"%d\"" % (self._desktop.getIndexInParent(),))
+
+	def test_getLocalizedRoleName(self, test):
+		ans = "unknown"
+		res = self._desktop.getLocalizedRoleName()
+		test.assertEqual(ans, res,
+				 "Expected LocalizedRoleName - \"%s\". Recieved - \"%s\"" % (ans, res,))
+
+	def test_getRelationSet(self, test):
+		rset = self._desktop.getRelationSet()
+		test.assertEqual(rset, [],
+				 "Expected relation set - \"[]\". Recieved - \"%s\"" % (rset,))
+
+	def test_getRole(self, test):
+		test.assertEqual(self._desktop.getRole(), pyatspi.ROLE_UNKNOWN,
+				 "Expected role - \"ROLE_UNKNOWN\". Recieved - \"%s\"" % (self._desktop.getRole(),))
+
+	def test_getRoleName(self, test):
+		ans = "unknown"
+		res = self._desktop.getRoleName()
+		test.assertEqual(ans, res,
+				 "Expected RoleName - \"%s\". Recieved - \"%s\"" % (ans, res,))
+
+	def test_getState(self, test):
+		state = self._desktop.getState()
+		res = pyatspi.StateSet()
+		if not state.equals(res):
+			test.fail("Desktop state set is not empty")
+
+	def test_childCount(self, test):
+		test.assertEqual(self._desktop.childCount, 1,
+				 "Expected childCount - \"1\". Recieved - \"%d\"" % (self._desktop.childCount,))
+
+	def test_description(self, test):
+		description = ""
+		test.assertEqual(self._desktop.description, description,
+			"Expected description - \"%s\". Recieved - \"%s\"" % (description, self._desktop.description,))
+
+	def test_contains(self, test):
+		pass
+
+	def test_getAccessibleAtPoint(self, test):
+		pass
+
+	def test_getExtents(self, test):
+		comp = self._desktop.queryComponent()
+ 
+		extents = comp.getExtents(0)
+		expected = pyatspi.BoundingBox(*(0,0,1024, 768))
+		test.assertEqual(extents, expected, 
+				 "Extents not correct. Expected (%d, %d, %d, %d), Recieved (%d, %d, %d, %d)"
+				 % (expected[0], expected[1], expected[2], expected[3], 
+					extents[0], extents[1], extents[2], extents[3]))
+
+	def test_getPosition(self, test):
+		comp = self._desktop.queryComponent()
+
+		position = comp.getPosition(0)
+		test.assertEqual(position, (0,0), 
+				 "Position not correct. Expected (%d, %d) Recieved (%d, %d)"
+				 % (0, 0, position[0], position[1]))
+
+	def test_getSize(self, test):
+		comp = self._desktop.queryComponent()
+ 
+		size = comp.getSize()
+		test.assertEqual(size, (1024, 768), 
+				 "Size not correct. Expected (%d, %d) Recieved (%d, %d)"
+				 % (1024, 768, size[0], size[1]))
+
+	def test_getLayer(self, test):
+		comp = self._desktop.queryComponent()
+ 
+		layer = comp.getLayer()
+		test.assertEqual(layer, pyatspi.LAYER_WIDGET, 
+				 "Layer not correct. Expected %d, Recieved %d"
+				 % (layer, pyatspi.LAYER_WIDGET))
+
+	def test_getMDIZOrder(self, test):
+		comp = self._desktop.queryComponent()
+ 
+		mdizo = comp.getMDIZOrder()
+		test.assertEqual(mdizo, 0, 
+				 "ZOrder not correct. Expected %d, Recieved %d"
+				 % (0, mdizo))
+
+	def test_grabFocus(self, test):
+		pass
+
+	def test_registerFocusHandler(self, test):
+		pass
+
+	def test_deregisterFocusHandler(self, test):
+		pass
+
+	def test_getAlpha(self, test):
+		pass
+
+	def teardown(self, test):
+		pass
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/Makefile.am pyatspi2/tests/pyatspi/Makefile.am
--- pyatspi2.old/tests/pyatspi/Makefile.am	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/Makefile.am	2019-08-26 23:04:09.541759565 +0200
@@ -0,0 +1,26 @@
+if SET_GTK_MODULE
+gtk_module_dir = $(libdir)/$(GTK_MODULE_DIR)
+else
+gtk_module_dir = $(GTK_MODULE_DIR)
+endif
+
+SUBDIRS = pasytest
+
+EXTRA_DIST = \
+	accessibletest.py\
+	actiontest.py\
+	componenttest.py\
+	desktoptest.py\
+	statetest.py\
+	Makefile.am\
+	Makefile.in\
+	setvars.sh\
+	relationtest.py\
+	runtests.sh\
+	testrunner
+
+TESTS_ENVIRONMENT = top_builddir=$(top_builddir) top_srcdir=$(top_srcdir) gtk_module_dir=$(gtk_module_dir)
+
+TESTS = runtests.sh
+
+CLEANFILES = *.pyc
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/pasytest/COPYING-PSF pyatspi2/tests/pyatspi/pasytest/COPYING-PSF
--- pyatspi2.old/tests/pyatspi/pasytest/COPYING-PSF	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/pasytest/COPYING-PSF	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,45 @@
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using this software ("Python") in source or binary form and
+its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python alone
+or in any derivative version, provided, however, that PSF's License
+Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Python Software Foundation;
+All Rights Reserved" are retained in Python alone or in any derivative
+version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python.
+
+4. PSF is making Python available to Licensee on an "AS IS"
+basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee.  This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/pasytest/Events.py pyatspi2/tests/pyatspi/pasytest/Events.py
--- pyatspi2.old/tests/pyatspi/pasytest/Events.py	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/pasytest/Events.py	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,81 @@
+#C#-Style Events in Python
+#Taken from http://code.activestate.com/recipes/410686/
+#Copyright 2005-2008 Zoran Isailovski
+#
+#This file is distributed under the terms of the PSF (Python Software
+#Foundation) license. See the COPYING file in this directory
+
+class Events:
+	def __getattr__(self, name):
+		if hasattr(self.__class__, '__events__'):
+			assert name in self.__class__.__events__, \
+					 "Event '%s' is not declared" % name
+		self.__dict__[name] = ev = _EventSlot(name)
+		return ev
+	def __repr__(self): return 'Events' + str(list(self))
+	__str__ = __repr__
+	def __len__(self): return NotImplemented
+	def __iter__(self):
+		def gen(dictitems=self.__dict__.items()):
+			for attr, val in dictitems:
+				if isinstance(val, _EventSlot):
+					yield val
+		return gen()
+
+#------------------------------------------------------------------------------
+
+class _EventSlot:
+	def __init__(self, name):
+		self.targets = []
+		self.__name__ = name
+	def __repr__(self):
+		return 'event ' + self.__name__
+	def __call__(self, *a, **kw):
+		for f in self.targets: f(*a, **kw)
+	def __iadd__(self, f):
+		self.targets.append(f)
+		return self
+	def __isub__(self, f):
+		while f in self.targets: self.targets.remove(f)
+		return self
+
+#------------------------------------------------------------------------------
+
+if __name__ == '__main__':
+
+	class MyEvents(Events):
+		__events__ = ('OnChange', )
+
+	class ValueModel(object):
+		def __init__(self):
+			self.events = MyEvents()
+			self.__value = None
+		def __set(self, value):
+			if (self.__value == value): return
+			self.__value = value
+			self.events.OnChange()
+			##self.events.OnChange2() # would fail
+		def __get(self):
+			return self.__value
+		Value = property(__get, __set, None, 'The actual value')
+
+	class SillyView(object):
+		def __init__(self, model):
+			self.model = model
+			model.events.OnChange += self.DisplayValue
+			##model.events.OnChange2 += self.DisplayValue # would raise exeception
+		def DisplayValue(self):
+			print self.model.Value
+
+
+	model = ValueModel()
+	view = SillyView(model)
+
+	print '\n--- Events Demo ---'
+	# Events in action
+	for i in range(5):
+		model.Value = 2*i + 1
+	# Events introspection
+	print model.events
+	for event in model.events:
+		print event
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/pasytest/__init__.py pyatspi2/tests/pyatspi/pasytest/__init__.py
--- pyatspi2.old/tests/pyatspi/pasytest/__init__.py	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/pasytest/__init__.py	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,16 @@
+#Copyright (C) 2008 Codethink Ltd
+
+#his program 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 of the License, or
+#(at your option) any later version.
+
+#This program 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 this program; if not, write to the Free Software
+#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+from Pasy import PasyTestStep, PasyTestFunc, PasyTest
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/pasytest/Makefile.am pyatspi2/tests/pyatspi/pasytest/Makefile.am
--- pyatspi2.old/tests/pyatspi/pasytest/Makefile.am	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/pasytest/Makefile.am	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,7 @@
+EXTRA_DIST = \
+	Events.py\
+	Pasy.py\
+	__init__.py \
+	COPYING-PSF
+
+CLEANFILES = *.pyc
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/pasytest/Pasy.py pyatspi2/tests/pyatspi/pasytest/Pasy.py
--- pyatspi2.old/tests/pyatspi/pasytest/Pasy.py	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/pasytest/Pasy.py	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,147 @@
+#Copyright (C) 2008 Codethink Ltd
+
+#his program 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 of the License, or
+#(at your option) any later version.
+
+#This program 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 this program; if not, write to the Free Software
+#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+from gi.repository import GObject, GLib
+from Events import Events
+
+import traceback
+
+PASY_TEST_NOT_STARTED = 0
+PASY_TEST_IN_PROGRESS = 1
+PASY_TEST_FAIL = 2
+PASY_TEST_WIN = 3
+
+class PasyEvents(Events):
+	__events__ = ('finished', )
+
+class PasyTestStep(object):
+
+	def __init__(self, name):
+		self.events = PasyEvents()
+		self._state = PASY_TEST_NOT_STARTED
+                self.failMsg = None
+
+		self._name = name
+
+	def win(self):
+		if self._state == PASY_TEST_IN_PROGRESS:
+			self._state = PASY_TEST_WIN
+			self.events.finished()
+	
+	def fail(self, msg):
+		if self._state == PASY_TEST_IN_PROGRESS:
+			self._state = PASY_TEST_FAIL
+			self.failMsg = msg
+			self.events.finished()
+
+	def assertEqual(self, a, b, msg):
+		if a != b:
+			self.fail(msg)
+
+	def assertNotEqual(self, a, b, msg):
+		if a == b:
+			self.fail(msg)
+
+	def run(self):
+		self._state = PASY_TEST_IN_PROGRESS
+		self.entry()
+
+	def report(self):
+		if self._state == PASY_TEST_WIN:
+			return "%s - PASSED" % (self._name,)
+		elif self._state == PASY_TEST_FAIL:
+			return "%s - FAILED - %s" % (self._name, self.failMsg)
+		else:
+			return "%s - INCOMPLETE" % (self._name,)
+
+	@property
+	def state(self):
+		return self._state
+
+class PasyTestFunc(PasyTestStep):
+	
+	def __init__(self, name, func):
+		PasyTestStep.__init__(self, name)
+		self._func = func
+
+	def entry(self):
+		try:
+			self._func(self)
+		except Exception, e:
+			self.fail(e.message)
+			traceback.print_exc()
+		self.win()
+
+class PasyTest(PasyTestStep):
+
+	__tests__ = []
+
+	def __init__(self, name, cont):
+		PasyTestStep.__init__(self, name)
+
+		self._cont = cont
+		self._tests = []
+
+		for name in self.__tests__:
+			func = getattr(self, name)
+			self._addfunc(func.func_name, func)
+
+	def _addfunc(self, name, func):
+		functest = PasyTestFunc(func.func_name, func)
+		self._tests.append(functest)
+
+	def entry(self):
+		self._iter = self._test_iterator()
+		GLib.idle_add(self.idle_handler)
+
+	def idle_handler(self):
+		try:
+			step = self._iter.next()
+			def finished_handler():
+				if step.state == PASY_TEST_WIN or self._cont == True:
+					GLib.idle_add(self.idle_handler)
+				elif step.state == PASY_TEST_FAIL and self._cont == False:
+					self.fail("Sub test %s Failed" % step._name)
+			step.events.finished += finished_handler
+			step.run()
+		except StopIteration:
+			# No More tests, check for success or fail
+			succeeded = True
+			for test in self._tests:
+				succeeded = succeeded and (test.state == PASY_TEST_WIN)
+			if succeeded:
+				self.win()
+			else:
+				self.fail()
+		return False
+
+	def _test_iterator(self):
+		for test in self._tests:
+			yield test
+
+	def report(self):
+		if self._state == PASY_TEST_WIN:
+			header =  "%s - PASSED" % (self._name,)
+		elif self._state == PASY_TEST_FAIL:
+			header =  "%s - FAILED" % (self._name,)
+		else:
+			header =  "%s - INCOMPLETE" %s (self._name,)
+
+		step_messages = []
+		for test in self._tests:
+			step_messages.append(test.report())
+
+		step_report =  "\n\t".join(step_messages)
+		return header + "\n\t" + step_report
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/relationtest.py pyatspi2/tests/pyatspi/relationtest.py
--- pyatspi2.old/tests/pyatspi/relationtest.py	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/relationtest.py	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,89 @@
+#
+# Copyright 2008 Codethink Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+
+import dbus
+from gi.repository import GObject
+import os.path
+
+from xml.dom import minidom
+import os
+
+from pasytest import PasyTest as _PasyTest
+
+import pyatspi
+
+class RelationTest(_PasyTest):
+
+	__tests__ = ["setup",
+		     "teardown",
+		     "test_getRelationType",
+		     "test_getRelationTypeName",
+		     "test_getNTargets",
+		     "test_getTarget",
+		     ]
+
+	def __init__(self, bus, path):
+		_PasyTest.__init__(self, "Relation", False)
+		self._bus = bus
+		self._path = path
+
+	def setup(self, test):
+		self._registry = pyatspi.Registry()
+		self._desktop = self._registry.getDesktop(0)
+                self._root = pyatspi.findDescendant (self._desktop, lambda x: x.name == "atspi-test-main" and x.getRole() == pyatspi.ROLE_APPLICATION)
+		self._rset = self._root.getRelationSet()
+		test.assertEqual(len(self._rset), 4, "Num relations expected %d, recieved %d" % (4, len(self._rset)))
+
+	def test_getRelationType(self, test):
+		expected = [pyatspi.RELATION_EMBEDS,
+			    pyatspi.RELATION_PARENT_WINDOW_OF,
+			    pyatspi.RELATION_DESCRIBED_BY,
+			    pyatspi.RELATION_POPUP_FOR,]
+		rtypes = [rel.getRelationType() for rel in self._rset]
+		for exp, type in zip(expected, rtypes):
+			test.assertEqual(exp, type, "Relation type expected %s, recieved %s" % (exp, type))
+
+	def test_getRelationTypeName(self, test):
+		# FIXME This may not have been implemented in CORBA.
+		#       Completely unused?
+		pass
+
+	def test_getNTargets(self, test):
+		expected = [1, 1, 1, 3]
+		ntargs = [rel.getNTargets() for rel in self._rset]
+		for exp, ntarg in zip(expected, ntargs):
+			test.assertEqual(exp, ntarg, "Number of targets expected %s, recieved %s" % (exp, ntarg))
+
+	def test_getTarget(self, test):
+		rone = self._rset[0]
+		tone = rone.getTarget(0)
+		tonename = tone.name
+		test.assertEqual(tonename, "r1", "Target name expected %s, recieved %s" % ("r1", tonename))
+		tonerole = tone.getRoleName()
+		test.assertEqual(tonerole, "invalid", "Target RoleName expected %s, recieved %s" % ("invalid", tonename))
+
+		rtwo = self._rset[3]
+		ttwo = rtwo.getTarget(2)
+		ttwoname = ttwo.name
+		test.assertEqual(ttwoname, "m3", "Target name expected %s, recieved %s" % ("m3", ttwoname))
+		ttworole = ttwo.getRoleName()
+		test.assertEqual(ttworole, "invalid", "Target RoleName expected %s, recieved %s" % ("invalid", ttwoname))
+
+	def teardown(self, test):
+		pass
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/runtests.sh pyatspi2/tests/pyatspi/runtests.sh
--- pyatspi2.old/tests/pyatspi/runtests.sh	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/runtests.sh	2019-08-27 16:36:24.955047818 +0200
@@ -0,0 +1,25 @@
+export PYTHONPATH=$top_srcdir:$top_srcdir/tests/pyatspi
+
+export TEST_DATA_DIRECTORY=$top_srcdir/tests/data
+export TEST_ATSPI_LIBRARY=$gtk_module_dir/libatk-bridge.so
+export TEST_MODULES_DIRECTORY=$top_builddir/tests/apps/.libs
+export TEST_APPLICATION=$top_builddir/tests/apps/test-application
+
+run()
+{
+  chmod a+x $top_builddir/tests/pyatspi/testrunner
+  $top_builddir/tests/pyatspi/testrunner -l $1 -m $2 -n $3
+  result=$?
+  if [ $result -ne 0 ]; then
+    ret=$result
+    fi
+}
+
+ret=0
+run libaccessibleapp.so accessibletest AccessibleTest
+run libactionapp.so actiontest ActionTest
+run libaccessibleapp.so collectiontest AccessibleTest
+run libcomponentapp.so componenttest ComponentTest
+run librelationapp.so relationtest RelationTest
+run libaccessibleapp.so statetest StateTest
+exit $ret
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/setvars.sh pyatspi2/tests/pyatspi/setvars.sh
--- pyatspi2.old/tests/pyatspi/setvars.sh	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/setvars.sh	2019-08-26 23:04:09.541759565 +0200
@@ -0,0 +1,6 @@
+export PYTHONPATH=../../
+
+export TEST_DATA_DIRECTORY=../data
+export TEST_ATSPI_LIBRARY=../../atk-adaptor/.libs/libspiatk.so
+export TEST_MODULES_DIRECTORY=../apps/.libs
+export TEST_APPLICATION=../apps/test-application
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/statetest.py pyatspi2/tests/pyatspi/statetest.py
--- pyatspi2.old/tests/pyatspi/statetest.py	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/statetest.py	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,120 @@
+#
+# Copyright 2008 Codethink Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+
+import dbus
+from gi.repository import GObject
+import os.path
+
+from xml.dom import minidom
+import os
+
+from pasytest import PasyTest as _PasyTest
+
+import pyatspi
+from pyatspi import StateSet
+
+os = [pyatspi.STATE_MULTISELECTABLE,
+      pyatspi.STATE_PRESSED,
+      pyatspi.STATE_SHOWING,
+      pyatspi.STATE_TRANSIENT,
+      pyatspi.STATE_COLLAPSED,
+      pyatspi.STATE_EDITABLE,]
+
+class StateTest(_PasyTest):
+
+	__tests__ = ["setup",
+		     "test_contains",
+		     "test_add",
+		     "test_remove",
+		     "test_equals",
+		     "test_compare",
+		     "test_isEmpty",
+		     "test_getStates",
+		     "teardown",
+		     ]
+
+	def __init__(self, bus, path):
+		_PasyTest.__init__(self, "State", False)
+
+	def setup(self, test):
+		pass
+
+	def test_contains(self, test):
+		state = StateSet(*os)
+		if not state.contains(pyatspi.STATE_PRESSED):
+			test.fail("Does not find contained state")
+		if state.contains(pyatspi.STATE_ACTIVE):
+			test.fail("Finds state not contained")
+
+	def test_add(self, test):
+		state = StateSet()
+		state.add(pyatspi.STATE_PRESSED)
+		if not state.contains(pyatspi.STATE_PRESSED):
+			test.fail("State not added")
+
+	def test_remove(self, test):
+		state = StateSet(*os)
+		state.remove(pyatspi.STATE_PRESSED)
+		if state.contains(pyatspi.STATE_PRESSED):
+			test.fail("State not removed")
+
+	def test_equals(self, test):
+		one = StateSet(*os)
+		two = StateSet(*os)
+		if not one.equals(two):
+			test.fail("Same states not found equal")
+		two.remove(pyatspi.STATE_PRESSED)
+		if two.equals(one):
+			test.fail("Unequal states found equal")
+
+	def test_isEmpty(self, test):
+		emp = StateSet()
+		if not emp.isEmpty():
+			test.fail("Empty state found non-empty")
+		emp.add(pyatspi.STATE_PRESSED)
+		if emp.isEmpty():
+			test.fail("State incorrectly found empty")
+
+	def test_compare(self, test):
+		one = StateSet(*os)
+		two = StateSet(*os)
+
+		onemtwo = one.compare(two)
+		if not onemtwo.isEmpty():
+			test.fail("Equal states when compared yeilds non-empty state")
+
+		one.add(pyatspi.STATE_ACTIVE)
+		onemtwo = one.compare(two)
+		
+		act = StateSet(pyatspi.STATE_ACTIVE)
+		if not onemtwo.equals(act):
+			test.fail("Compared states do not yeild correct state")
+
+	def test_getStates(self, test):
+		state = StateSet(*os)
+
+		states = state.getStates()
+		cone = set(states)
+		ctwo = set(os)
+
+		if not (cone.issubset(ctwo) and ctwo.issubset(cone)):
+			test.fail("States not reported correctly")
+
+	def teardown(self, test):
+		pass
diff --exclude .svn --exclude .git --exclude CVS --exclude .hg -urN pyatspi2.old/tests/pyatspi/testrunner.in pyatspi2/tests/pyatspi/testrunner.in
--- pyatspi2.old/tests/pyatspi/testrunner.in	1970-01-01 01:00:00.000000000 +0100
+++ pyatspi2/tests/pyatspi/testrunner.in	2019-08-27 19:10:03.881588561 +0200
@@ -0,0 +1,116 @@
+#!@PYTHON@
+#
+# Copyright 2008 Codethink Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+
+from gi.repository import GObject, GLib
+import dbus
+import sys
+import os
+import time
+from random import randint
+
+from optparse import OptionParser
+from pasytest import PasyTest
+
+from dbus.mainloop.glib import DBusGMainLoop
+
+DBusGMainLoop(set_as_default=True)
+
+def run_test_app(module_name, dbus_name=None, wait_for_debug=False):
+	import os
+	from subprocess import Popen
+
+	test_data_directory = os.environ["TEST_DATA_DIRECTORY"]
+	test_modules_directory = os.environ["TEST_MODULES_DIRECTORY"]
+	test_atspi_library = os.environ["TEST_ATSPI_LIBRARY"]
+	test_application = os.environ["TEST_APPLICATION"]
+
+	test_module = os.path.join(test_modules_directory, module_name)
+
+	if (dbus_name):
+		print " ".join([test_application,
+			"--atspi-dbus-name", dbus_name,
+			"--test-dbus-name", dbus_name,
+			"--test-atspi-library", test_atspi_library,
+			"--test-module", test_module,
+			"--test-data-directory", test_data_directory,])
+		pop = Popen([test_application,
+			"--atspi-dbus-name", dbus_name,
+			"--test-dbus-name", dbus_name,
+			"--test-atspi-library", test_atspi_library,
+			"--test-module", test_module,
+			"--test-data-directory", test_data_directory,])
+	else:
+		print " ".join([test_application,
+			"--test-atspi-library", test_atspi_library,
+			"--test-module", test_module,
+			"--test-data-directory", test_data_directory,])
+		pop = Popen([test_application,
+			"--test-atspi-library", test_atspi_library,
+			"--test-module", test_module,
+			"--test-data-directory", test_data_directory,])
+
+	wait_message = """
+	The test application %s has been started with PID %d.
+	
+	To continue the test press ENTER.\n\n
+	"""
+	if (wait_for_debug):
+		raw_input(wait_message % (module_name, pop.pid))
+
+def main(argv):
+	parser = OptionParser()
+	parser.add_option("-l", "--library", dest="test_library")
+	parser.add_option("-m", "--module", dest="test_module")
+	parser.add_option("-n", "--name", dest="test_name")
+	parser.add_option("-w", "--wait", action="store_true", dest="wait", default=False)
+	(options, args) = parser.parse_args()
+
+	bus = dbus.SessionBus()
+	name = "test.atspi.R" + str(randint(1, 1000)) 
+
+	app = run_test_app(options.test_library, name, wait_for_debug=options.wait)
+	time.sleep(1)
+	print "Started test app on bus name %s" % (name,)
+
+	to = bus.get_object(name, "/org/codethink/atspi/test")
+	test = dbus.Interface(to, "org.codethink.atspi.test")
+
+	# Run the test script here
+	os.environ["ATSPI_TEST_APP_NAME"] = name
+	module = __import__(options.test_module)
+	test_class = getattr(module, options.test_name)
+	test_object = test_class(bus, name)
+	test_object.run()
+
+	loop = GLib.MainLoop()
+
+	def finished_handler():
+		loop.quit()
+		print "\n" + test_object.report() + "\n"
+		if test_object.failMsg:
+			sys.exit (1)
+		test.finish()
+
+	test_object.events.finished += finished_handler
+
+	loop.run()
+
+if __name__=="__main__":
+	sys.exit(main(sys.argv))
