static gboolean
perform_test(guint max_total_log_size,
             InfTextChunk* initial,
             GSList* users,
             GSList* requests,
             GError** error)
{
  InfTextBuffer* buffer;
  InfCommunicationManager* manager;
  InfIo* io;
  InfTextSession* session;
  InfAdoptedAlgorithm* algorithm;

  InfUserTable* user_table;
  InfTextUser* user;
  gchar* user_name;

  GSList* item;
  xmlNodePtr request;
  gboolean result;
  GError* local_error;
  
  guint verify_user_id;
  InfAdoptedUser* verify_user;
  guint verify_log_size;
  gint verify_can_undo;
  gint verify_can_redo;

  InfAdoptedRequestLog* log;
  guint log_size;

  buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8"));
  inf_text_buffer_insert_chunk(buffer, 0, initial, NULL);

  manager = inf_communication_manager_new();
  io = INF_IO(inf_standalone_io_new());
  user_table = inf_user_table_new();
  local_error = NULL;

  for(item = users; item != NULL; item = g_slist_next(item))
  {
    user_name = g_strdup_printf("User_%u", GPOINTER_TO_UINT(item->data));

    user = INF_TEXT_USER(
      g_object_new(
        INF_TEXT_TYPE_USER,
        "id", GPOINTER_TO_UINT(item->data),
        "name", user_name,
        "status", INF_USER_ACTIVE,
        "flags", 0,
        NULL
      )
    );

    g_free(user_name);
    inf_user_table_add_user(user_table, INF_USER(user));
    g_object_unref(user);
  }

  session = INF_TEXT_SESSION(
    g_object_new(
      INF_TEXT_TYPE_SESSION,
      "communication-manager", manager,
      "buffer", buffer,
      "io", io,
      "user_table", user_table,
      "max-total-log-size", max_total_log_size,
      NULL
    )
  );
  
  algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session));

  g_object_unref(io);
  g_object_unref(manager);
  g_object_unref(user_table);
  g_object_unref(buffer);

  for(item = requests; item != NULL; item = item->next)
  {
    request = (xmlNodePtr)item->data;
    
    if(strcmp((const char*)request->name, "request") == 0)
    {
      /* Request */
      result = inf_communication_object_received(
        INF_COMMUNICATION_OBJECT(session),
        NULL,
        request,
        &local_error
      );
      
      if(local_error != NULL)
        goto fail;
    }
    else
    {
      /* TODO: Make an extra function out of this: */
      /* Verify */
      result = inf_xml_util_get_attribute_uint_required(
        request,
        "user",
        &verify_user_id,
        &local_error
      );
      
      if(result == FALSE)
        goto fail;

      verify_user = INF_ADOPTED_USER(
        inf_user_table_lookup_user_by_id(user_table, verify_user_id)
      );

      if(verify_user == NULL)
      {
        g_set_error(
          error,
          inf_test_text_cleanup_error_quark(),
          INF_TEST_TEXT_CLEANUP_USER_UNAVAILABLE,
          "User ID '%u' not available",
          verify_user_id
        );
        
        goto fail;
      }

      result = inf_xml_util_get_attribute_uint(
        request,
        "log-size",
        &verify_log_size,
        &local_error
      );

      if(local_error) goto fail;

      if(result)
      {
        log = inf_adopted_user_get_request_log(INF_ADOPTED_USER(verify_user));
        log_size = inf_adopted_request_log_get_end(log) -
          inf_adopted_request_log_get_begin(log);
        if(verify_log_size != log_size)
        {
          g_set_error(
            error,
            inf_test_text_cleanup_error_quark(),
            INF_TEST_TEXT_CLEANUP_VERIFY_FAILED,
            "Log size does not match; got %u, but expected %u",
            log_size,
            verify_log_size
          );

          goto fail;
        }
      }
      
      result = inf_xml_util_get_attribute_int(
        request,
        "can-undo",
        &verify_can_undo,
        &local_error
      );

      if(local_error) goto fail;

      if(result)
      {
        result = inf_adopted_algorithm_can_undo(algorithm, verify_user);
        if(result != verify_can_undo)
        {
          g_set_error(
            error,
            inf_test_text_cleanup_error_quark(),
            INF_TEST_TEXT_CLEANUP_VERIFY_FAILED,
            "can-undo does not match; got %d, but expected %d",
            (guint)result,
            verify_can_undo
          );

          goto fail;
        }
      }

      result = inf_xml_util_get_attribute_int(
        request,
        "can-redo",
        &verify_can_redo,
        &local_error
      );

      if(local_error) goto fail;

      if(result)
      {
        result = inf_adopted_algorithm_can_redo(algorithm, verify_user);
        if(result != verify_can_redo)
        {
          g_set_error(
            error,
            inf_test_text_cleanup_error_quark(),
            INF_TEST_TEXT_CLEANUP_VERIFY_FAILED,
            "can-redo does not match; got %d, but expected %d",
            (guint)result,
            verify_can_redo
          );

          goto fail;
        }
      }
    }
  }

  g_object_unref(session);
  return TRUE;

fail:
  g_object_unref(session);
  if(local_error) g_propagate_error(error, local_error);
  return FALSE;
}
Beispiel #2
0
void Gobby::OperationOpen::read_finish()
{
	// If the last character is a newline character, remove it.
	GtkTextIter end_iter, test_iter;
	gtk_text_buffer_get_end_iter(m_content, &end_iter);
	test_iter = end_iter;
	if(gtk_text_iter_backward_char(&test_iter))
	{
		if(gtk_text_iter_get_char(&test_iter) == '\n')
		{
			gtk_text_buffer_delete(
				m_content, &test_iter, &end_iter);
		}
	}

	gtk_text_buffer_set_modified(m_content, FALSE);

	GtkTextIter insert_iter;
	GtkTextMark* insert = gtk_text_buffer_get_insert(m_content);
	gtk_text_buffer_get_iter_at_mark(m_content, &insert_iter, insert);

	InfUser* user = INF_USER(g_object_new(
		INF_TEXT_TYPE_USER,
		"id", 1,
		"flags", INF_USER_LOCAL,
		"name", m_preferences.user.name.get().c_str(),
		/* The user is made active when the user
		 * switches to the document. */
		"status", INF_USER_INACTIVE,
		"hue", m_preferences.user.hue.get(),
		"caret-position", gtk_text_iter_get_offset(&insert_iter),
		static_cast<void*>(NULL)));

	InfUserTable* user_table = inf_user_table_new();
	inf_user_table_add_user(user_table, user);
	g_object_unref(user);

	InfTextGtkBuffer* text_gtk_buffer =
		inf_text_gtk_buffer_new(m_content, user_table);
	g_object_unref(user_table);

	ConnectionManager& connection_manager =
		get_browser().get_connection_manager();
	InfCommunicationManager* communication_manager =
		connection_manager.get_communication_manager();

	InfBrowser* browser = m_parent.get_browser();

	InfIo* io;
	g_object_get(G_OBJECT(browser), "io", &io, NULL);

	InfTextSession* session = inf_text_session_new_with_user_table(
		communication_manager, INF_TEXT_BUFFER(text_gtk_buffer), io,
		user_table, INF_SESSION_RUNNING, NULL, NULL);

	g_object_unref(io);
	g_object_unref(text_gtk_buffer);

	InfRequest* request = inf_browser_add_note(
		m_parent.get_browser(), m_parent.get_browser_iter(),
		m_name.c_str(), "InfText", NULL,
		INF_SESSION(session), TRUE,
		on_request_finished_static, this);
	g_object_unref(session);

	if(request != NULL)
	{
		m_request = request;
		g_object_ref(m_request);

		// TODO: We can remove the node watch here, but need to have
		// the browser available in on_request_finished then. Maybe
		// just disconnect the signal, or bind it.
	}
}
static gboolean
infd_note_plugin_text_read_user(InfUserTable* user_table,
                                xmlNodePtr node,
                                GError** error)
{
  guint id;
  gdouble hue;
  xmlChar* name;
  gboolean result;
  InfUser* user;

  if(!inf_xml_util_get_attribute_uint_required(node, "id", &id, error))
    return FALSE;

  if(!inf_xml_util_get_attribute_double_required(node, "hue", &hue, error))
    return FALSE;

  name = inf_xml_util_get_attribute_required(node, "name", error);
  if(name == NULL)
    return FALSE;

  if(inf_user_table_lookup_user_by_id(user_table, id) != NULL)
  {
    g_set_error(
      error,
      g_quark_from_static_string("INF_NOTE_PLUGIN_TEXT_ERROR"),
      INFD_NOTE_PLUGIN_TEXT_ERROR_USER_EXISTS,
      "User with ID %u exists already",
      id
    );

    result = FALSE;
  }
  else
  {
    if(inf_user_table_lookup_user_by_name(user_table, (const gchar*)name))
    {
      g_set_error(
        error,
        g_quark_from_static_string("INF_NOTE_PLUGIN_TEXT_ERROR"),
        INFD_NOTE_PLUGIN_TEXT_ERROR_USER_EXISTS,
        "User with name `%s' exists already",
        (const gchar*)name
      );

      result = FALSE;
    }
    else
    {
      user = INF_USER(
        g_object_new(
          INF_TEXT_TYPE_USER,
          "id", id,
          "name", name,
          "hue", hue,
          NULL
        )
      );

      inf_user_table_add_user(user_table, user);
      g_object_unref(user);
      result = TRUE;
    }
  }

  xmlFree(name);
  return result;
}