/* Note plugin implementation */
static InfSession*
infinoted_plugin_note_text_session_new(InfIo* io,
                                       InfCommunicationManager* manager,
                                       InfSessionStatus status,
                                       InfCommunicationGroup* sync_group,
                                       InfXmlConnection* sync_connection,
                                       const gchar* path,
                                       gpointer user_data)
{
  InfTextSession* session;
  InfTextBuffer* buffer;

  buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8"));

  session = inf_text_session_new(
    manager,
    buffer,
    io,
    status,
    sync_group,
    sync_connection
  );

  g_object_unref(buffer);

  return INF_SESSION(session);
}
static InfSession*
infinoted_plugin_note_text_session_read(InfdStorage* storage,
                                        InfIo* io,
                                        InfCommunicationManager* manager,
                                        const gchar* path,
                                        gpointer user_data,
                                        GError** error)
{
  InfUserTable* user_table;
  InfTextBuffer* buffer;
  gboolean result;
  InfTextSession* session;

  g_assert(INFD_IS_FILESYSTEM_STORAGE(storage));

  user_table = inf_user_table_new();
  buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8"));

  result = inf_text_filesystem_format_read(
    INFD_FILESYSTEM_STORAGE(storage),
    path,
    user_table,
    buffer,
    error
  );

  if(result == FALSE)
  {
    g_object_unref(user_table);
    g_object_unref(buffer);
    return NULL;
  }

  session = inf_text_session_new_with_user_table(
    manager,
    buffer,
    io,
    user_table,
    INF_SESSION_RUNNING,
    NULL,
    NULL
  );

  g_object_unref(user_table);
  g_object_unref(buffer);

  return INF_SESSION(session);
}
static InfSession*
infd_note_plugin_text_session_new(InfIo* io,
                                  InfCommunicationManager* manager,
                                  InfSessionStatus status,
                                  InfCommunicationHostedGroup* sync_group,
                                  InfXmlConnection* sync_connection,
                                  gpointer user_data)
{
  InfTextSession* session;

  session = inf_text_session_new(
    manager,
    INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")),
    io,
    status,
    INF_COMMUNICATION_GROUP(sync_group),
    sync_connection
  );

  return INF_SESSION(session);
}
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;
}
Esempio n. 5
0
static gboolean
test_fixline(const gchar* initial_buffer_content,
             const gchar* initial_base_content,
             guint n_lines,
             InfTestTextFixlineOperation operation,
             InfTestTextFixlineTarget target,
             guint pos,
             gchar* text,
             const gchar* final_buffer_content,
             const gchar* final_base_content)
{
  InfStandaloneIo* io;
  InfTextBuffer* base;
  InfTextBuffer* buffer;

  /* Create the initial state */
  io = inf_standalone_io_new();
  base = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8"));

  inf_text_buffer_insert_text(
    base,
    0,
    initial_buffer_content,
    strlen(initial_buffer_content),
    strlen(initial_buffer_content),
    0
  );

  buffer = INF_TEXT_BUFFER(
    inf_text_fixline_buffer_new(INF_IO(io), base, n_lines)
  );

  /* Check the initial state */
  if(!check_buffer(base, initial_base_content, "Initial base"))
  {
    g_object_unref(io);
    g_object_unref(base);
    g_object_unref(buffer);
    return FALSE;
  }

  if(!check_buffer(buffer, initial_buffer_content, "Initial buf"))
  {
    g_object_unref(io);
    g_object_unref(base);
    g_object_unref(buffer);
    return FALSE;
  }

  /* Apply the operation */
  switch(operation)
  {
  case OP_NONE:
    break;
  case OP_INS:
    if(target == TG_BASE)
    {
      inf_text_buffer_insert_text(
        base,
        pos,
        text,
        strlen(text),
        strlen(text),
        0
      );
    }
    else if(target == TG_BUF)
    {
      inf_text_buffer_insert_text(
        buffer,
        pos,
        text,
        strlen(text),
        strlen(text),
        0
      );
    }
    break;
  case OP_DEL:
    if(target == TG_BASE)
      inf_text_buffer_erase_text(base, pos, GPOINTER_TO_UINT(text), 0);
    else if(target == TG_BUF)
      inf_text_buffer_erase_text(buffer, pos, GPOINTER_TO_UINT(text), 0);
    break;
  default:
    g_assert_not_reached();
    break;
  }

  /* Run any delayed action */
  inf_standalone_io_iteration_timeout(io, 0);

  /* Check the final state */
  if(!check_buffer(base, final_base_content, "Final base"))
  {
    g_object_unref(io);
    g_object_unref(base);
    g_object_unref(buffer);
    return FALSE;
  }

  if(!check_buffer(buffer, final_buffer_content, "Final buf"))
  {
    g_object_unref(io);
    g_object_unref(base);
    g_object_unref(buffer);
    return FALSE;
  }

  g_object_unref(io);
  g_object_unref(base);
  g_object_unref(buffer);

  return TRUE;
}
  InfTextUser* user;
  gchar* user_name;

  GSList* item;
  xmlNodePtr request;

  gboolean result;
  InfTextChunk* test_chunk;
  gchar* first;
  gchar* second;
  gsize first_bytes;
  gsize second_bytes;

  GTimer* timer;

  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();

  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,
static InfSession*
infd_note_plugin_text_session_read(InfdStorage* storage,
                                   InfIo* io,
                                   InfCommunicationManager* manager,
                                   const gchar* path,
                                   gpointer user_data,
                                   GError** error)
{
  InfUserTable* user_table;
  InfTextBuffer* buffer;
  InfTextSession* session;

  FILE* stream;
  xmlDocPtr doc;
  xmlErrorPtr xmlerror;
  xmlNodePtr root;
  xmlNodePtr child;
  gboolean result;

  g_assert(INFD_IS_FILESYSTEM_STORAGE(storage));

  user_table = inf_user_table_new();
  buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8"));

  /* TODO: Use a SAX parser for better performance */
  stream = infd_filesystem_storage_open(
    INFD_FILESYSTEM_STORAGE(storage),
    "InfText",
    path,
    "r",
    error
  );

  if(stream == NULL) return FALSE;

  doc = xmlReadIO(
    infd_note_plugin_text_session_read_read_func,
    infd_note_plugin_text_sesison_read_close_func,
    stream,
    path, /* TODO: Get some "infinote-filesystem-storage://" URL? */
    "UTF-8",
    XML_PARSE_NOWARNING | XML_PARSE_NOERROR
  );

  if(doc == NULL)
  {
    xmlerror = xmlGetLastError();

    g_set_error(
      error,
      g_quark_from_static_string("LIBXML2_PARSER_ERROR"),
      xmlerror->code,
      "Error parsing XML in file '%s': [%d]: %s",
      path,
      xmlerror->line,
      xmlerror->message
    );

    result = FALSE;
  }
  else
  {
    root = xmlDocGetRootElement(doc);
    if(strcmp((const char*)root->name, "inf-text-session") != 0)
    {
      g_set_error(
        error,
        g_quark_from_static_string("INF_NOTE_PLUGIN_TEXT_ERROR"),
        INFD_NOTE_PLUGIN_TEXT_ERROR_NOT_A_TEXT_SESSION,
        "Error processing file '%s': %s",
        path,
        "The document is not a text session"
      );

      result = FALSE;
    }
    else
    {
      for(child = root->children; child != NULL; child = child->next)
      {
        if(child->type != XML_ELEMENT_NODE)
          continue;

        if(strcmp((const char*)child->name, "user") == 0)
        {
          if(!infd_note_plugin_text_read_user(user_table, child, error))
          {
            g_prefix_error(error, "Error processing file '%s': ", path);
            result = FALSE;
            break;
          }
        }
        else if(strcmp((const char*)child->name, "buffer") == 0)
        {
          if(!infd_note_plugin_text_read_buffer(buffer, user_table,
                                                child, error))
          {
            g_prefix_error(error, "Error processing file '%s': ", path);
            result = FALSE;
            break;
          }
        }
        else
        {
          infd_note_plugin_text_session_unexpected_node(child, error);
          g_prefix_error(error, "Error processing file '%s': ", path);
          result = FALSE;
          break;
        }
      }

      if(child == NULL)
        result = TRUE;
    }

    xmlFreeDoc(doc);
  }

  if(result == FALSE)
    return NULL;

  session = inf_text_session_new_with_user_table(
    manager,
    buffer,
    io,
    user_table,
    INF_SESSION_RUNNING,
    NULL,
    NULL
  );

  return INF_SESSION(session);
}