result = nsComponentManager::CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, nsnull, NS_GET_IID(nsITransactionManager), (void **)&mgr);
mgr = do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
quick_batch_test(TestTransactionFactory *factory){  /*******************************************************************   *   * Create a transaction manager implementation:   *   *******************************************************************/  printf("Create transaction manager instance ... ");  PRInt32 i, numitems = 0;  nsITransactionManager  *mgr = 0;  nsITransaction *tx          = 0;  TestTransaction *tximpl   = 0;  nsITransaction *u1 = 0, *u2 = 0;  nsITransaction *r1 = 0, *r2 = 0;  nsresult result;  result = nsComponentManager::CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, nsnull,                                        NS_GET_IID(nsITransactionManager), (void **)&mgr);  if (NS_FAILED(result) || !mgr) {    printf("ERROR: Failed to create Transaction Manager instance.\n");    return NS_ERROR_OUT_OF_MEMORY;  }  printf("passed\n");  /*******************************************************************   *   * Make sure an unbalanced call to EndBatch() with empty undo stack   * throws an error!   *   *******************************************************************/  printf("Test unbalanced EndBatch() with empty undo stack ... ");  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->EndBatch();  if (result != NS_ERROR_FAILURE) {    printf("ERROR: EndBatch() returned unexpected status. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Make sure that an empty batch is not added to the undo stack   * when it is closed.   *   *******************************************************************/  printf("Test empty batch ... ");  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->BeginBatch();  if (NS_FAILED(result)) {    printf("ERROR: BeginBatch() failed. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->EndBatch();  if (NS_FAILED(result)) {    printf("ERROR: EndBatch() failed. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Execute 20 transactions. Afterwards, we should have 1   * transaction on the undo stack:   *   *******************************************************************/  printf("Execute 20 batched transactions ... ");  result = mgr->BeginBatch();  if (NS_FAILED(result)) {    printf("ERROR: BeginBatch() failed. (%d)\n", result);    return result;  }  for (i = 1; i <= 20; i++) {    tximpl = factory->create(mgr, NONE_FLAG);    if (!tximpl) {      printf("ERROR: Failed to allocate transaction %d.\n", i);      return NS_ERROR_OUT_OF_MEMORY;    }    tx = 0;    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);    if (NS_FAILED(result)) {      printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",             i, result);      return result;    }    result = mgr->DoTransaction(tx);    if (NS_FAILED(result)) {      printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);      return result;    }    tx->Release();  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->EndBatch();  if (NS_FAILED(result)) {    printf("ERROR: EndBatch() failed. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Execute 20 transient transactions. Afterwards, we should still   * have the same transaction on the undo stack:   *   *******************************************************************/  printf("Execute 20 batched transient transactions ... ");  u1 = u2 = r1 = r2 = 0;  result = mgr->PeekUndoStack(&u1);  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);    return result;  }  result = mgr->PeekRedoStack(&r1);  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);    return result;  }  result = mgr->BeginBatch();  if (NS_FAILED(result)) {    printf("ERROR: BeginBatch() failed. (%d)\n", result);    return result;  }  for (i = 1; i <= 20; i++) {    tximpl = factory->create(mgr, TRANSIENT_FLAG);    if (!tximpl) {      printf("ERROR: Failed to allocate transaction %d.\n", i);      return NS_ERROR_OUT_OF_MEMORY;    }    tx = 0;    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);    if (NS_FAILED(result)) {      printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",             i, result);      return result;    }    result = mgr->DoTransaction(tx);    if (NS_FAILED(result)) {      printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);      return result;    }    tx->Release();  }  result = mgr->EndBatch();  if (NS_FAILED(result)) {    printf("ERROR: EndBatch() failed. (%d)\n", result);    return result;  }  result = mgr->PeekUndoStack(&u2);  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);    return result;  }  if (u1 != u2) {    printf("ERROR: Top of undo stack changed. (%d)\n", result);    return NS_ERROR_FAILURE;  }  result = mgr->PeekRedoStack(&r2);  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);    return result;  }  if (r1 != r2) {    printf("ERROR: Top of redo stack changed. (%d)\n", result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Test nested batching. Afterwards, we should have 2 transactions   * on the undo stack:   *   *******************************************************************/  printf("Test nested batched transactions ... ");  result = mgr->BeginBatch();  if (NS_FAILED(result)) {    printf("ERROR: BeginBatch() failed. (%d)\n", result);    return result;  }  tximpl = factory->create(mgr, NONE_FLAG);  if (!tximpl) {    printf("ERROR: Failed to allocate transaction.\n");    return NS_ERROR_OUT_OF_MEMORY;  }  tx = 0;  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);  if (NS_FAILED(result)) {    printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);    return result;  }  result = mgr->DoTransaction(tx);  if (NS_FAILED(result)) {    printf("ERROR: Failed to execute transaction. (%d)\n", result);    return result;  }  tx->Release();  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->BeginBatch();  if (NS_FAILED(result)) {    printf("ERROR: BeginBatch() failed. (%d)\n", result);    return result;  }  tximpl = factory->create(mgr, NONE_FLAG);  if (!tximpl) {    printf("ERROR: Failed to allocate transaction.\n");    return NS_ERROR_OUT_OF_MEMORY;  }  tx = 0;  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);  if (NS_FAILED(result)) {    printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);    return result;  }  result = mgr->DoTransaction(tx);  if (NS_FAILED(result)) {    printf("ERROR: Failed to execute transaction. (%d)\n", result);    return result;  }  tx->Release();  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->BeginBatch();  if (NS_FAILED(result)) {    printf("ERROR: BeginBatch() failed. (%d)\n", result);    return result;  }  tximpl = factory->create(mgr, NONE_FLAG);  if (!tximpl) {    printf("ERROR: Failed to allocate transaction.\n");    return NS_ERROR_OUT_OF_MEMORY;  }  tx = 0;  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);  if (NS_FAILED(result)) {    printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);    return result;  }  result = mgr->DoTransaction(tx);  if (NS_FAILED(result)) {    printf("ERROR: Failed to execute transaction. (%d)\n", result);    return result;  }  tx->Release();  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->EndBatch();  if (NS_FAILED(result)) {    printf("ERROR: EndBatch() failed. (%d)\n", result);    return result;  }  result = mgr->EndBatch();  if (NS_FAILED(result)) {    printf("ERROR: EndBatch() failed. (%d)\n", result);    return result;  }  result = mgr->EndBatch();  if (NS_FAILED(result)) {    printf("ERROR: EndBatch() failed. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",           result);    return result;  }  if (numitems != 2) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Undo 2 batch transactions. Afterwards, we should have 0   * transactions on the undo stack and 2 on the redo stack.   *   *******************************************************************/  printf("Undo 2 batch transactions ... ");  for (i = 1; i <= 2; ++i) {    result = mgr->UndoTransaction();    if (NS_FAILED(result)) {      printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);      return result;    }  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",           result);    return result;  }  if (numitems != 2) {    printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Redo 2 batch transactions. Afterwards, we should have 2   * transactions on the undo stack and 0 on the redo stack.   *   *******************************************************************/  printf("Redo 2 batch transactions ... ");  for (i = 1; i <= 2; ++i) {    result = mgr->RedoTransaction();    if (NS_FAILED(result)) {      printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);      return result;    }  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",           result);    return result;  }  if (numitems != 2) {    printf("ERROR: GetNumberOfUndoItems() expected 2 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Call undo. Afterwards, we should have 1 transaction   * on the undo stack, and 1 on the redo stack:   *   *******************************************************************/  printf("Undo a batched transaction that was redone ... ");  result = mgr->UndoTransaction();  if (NS_FAILED(result)) {    printf("ERROR: Failed to undo transaction. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Make sure an unbalanced call to EndBatch() throws an error and   * doesn't affect the undo and redo stacks!   *   *******************************************************************/  printf("Test effect of unbalanced EndBatch() on undo and redo stacks ... ");  result = mgr->EndBatch();  if (result != NS_ERROR_FAILURE) {    printf("ERROR: EndBatch() returned unexpected status. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Make sure that an empty batch is not added to the undo stack   * when it is closed, and that it does not affect the undo and redo   * stacks.   *   *******************************************************************/  printf("Test effect of empty batch on undo and redo stacks ... ");  result = mgr->BeginBatch();  if (NS_FAILED(result)) {    printf("ERROR: BeginBatch() failed. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->EndBatch();  if (NS_FAILED(result)) {    printf("ERROR: EndBatch() failed. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Execute a new transaction. The redo stack should get pruned!   *   *******************************************************************/  printf("Check if new batched transactions prune the redo stack ... ");  result = mgr->BeginBatch();  if (NS_FAILED(result)) {    printf("ERROR: BeginBatch() failed. (%d)\n", result);    return result;  }  for (i = 1; i <= 20; i++) {    tximpl = factory->create(mgr, NONE_FLAG);    if (!tximpl) {      printf("ERROR: Failed to allocate transaction %d.\n", i);      return NS_ERROR_OUT_OF_MEMORY;    }    tx = 0;    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);    if (NS_FAILED(result)) {      printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",             i, result);      return result;    }    result = mgr->DoTransaction(tx);    if (NS_FAILED(result)) {      printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);      return result;    }    tx->Release();  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on redo stack with 1 items failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->EndBatch();  if (NS_FAILED(result)) {    printf("ERROR: EndBatch() failed. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",           result);    return result;  }  if (numitems != 2) {    printf("ERROR: GetNumberOfUndoItems() expected 2 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Call undo.   *   *******************************************************************/  printf("Call undo ... ");  // Move a transaction over to the redo stack, so that we have one  // transaction on the undo stack, and one on the redo stack!  result = mgr->UndoTransaction();  if (NS_FAILED(result)) {    printf("ERROR: Failed to undo transaction. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on redo stack with 1 items failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Test transaction DoTransaction() error:   *   *******************************************************************/  printf("Test transaction DoTransaction() error ... ");  tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);  if (!tximpl) {    printf("ERROR: Failed to allocate transaction.\n");    return NS_ERROR_OUT_OF_MEMORY;  }  tx     = 0;  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);  if (NS_FAILED(result)) {    printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);    return result;  }  u1 = u2 = r1 = r2 = 0;  result = mgr->PeekUndoStack(&u1);  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);    return result;  }  result = mgr->PeekRedoStack(&r1);  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);    return result;  }  result = mgr->BeginBatch();  if (NS_FAILED(result)) {    printf("ERROR: BeginBatch() failed. (%d)\n", result);    return result;  }  result = mgr->DoTransaction(tx);  if (NS_FAILED(result) && result != NS_ERROR_FAILURE) {    printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);    return result;  }  tx->Release();  result = mgr->EndBatch();  if (NS_FAILED(result)) {    printf("ERROR: EndBatch() failed. (%d)\n", result);    return result;  }  result = mgr->PeekUndoStack(&u2);  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);    return result;  }  if (u1 != u2) {    printf("ERROR: Top of undo stack changed. (%d)\n", result);    return NS_ERROR_FAILURE;  }  result = mgr->PeekRedoStack(&r2);  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);    return result;  }  if (r1 != r2) {    printf("ERROR: Top of redo stack changed. (%d)\n", result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfUndoItems() expected 5 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on empty redo stack. (%d)\n",           result);    return result;  }  if (numitems != 1) {    printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Test transaction UndoTransaction() error:   *   *******************************************************************/  printf("Test transaction UndoTransaction() error ... ");  tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);  if (!tximpl) {    printf("ERROR: Failed to allocate transaction.\n");    return NS_ERROR_OUT_OF_MEMORY;  }  tx     = 0;  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);  if (NS_FAILED(result)) {    printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);    return result;  }  result = mgr->BeginBatch();  if (NS_FAILED(result)) {    printf("ERROR: BeginBatch() failed. (%d)\n", result);    return result;  }  result = mgr->DoTransaction(tx);  if (NS_FAILED(result)) {    printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);    return result;  }  tx->Release();  result = mgr->EndBatch();  if (NS_FAILED(result)) {    printf("ERROR: EndBatch() failed. (%d)\n", result);    return result;  }  u1 = u2 = r1 = r2 = 0;  result = mgr->PeekUndoStack(&u1);  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);    return result;  }  result = mgr->PeekRedoStack(&r1);  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);    return result;  }  result = mgr->UndoTransaction();  if (NS_FAILED(result) && result != NS_ERROR_FAILURE) {    printf("ERROR: UndoTransaction() returned unexpected error. (%d)\n", result);    return result;  }  result = mgr->PeekUndoStack(&u2);  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);    return result;  }  if (u1 != u2) {    printf("ERROR: Top of undo stack changed. (%d)\n", result);    return NS_ERROR_FAILURE;  }  result = mgr->PeekRedoStack(&r2);  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);    return result;  }  if (r1 != r2) {    printf("ERROR: Top of redo stack changed. (%d)\n", result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",           result);    return result;  }  if (numitems != 2) {    printf("ERROR: GetNumberOfUndoItems() expected 2 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on empty redo stack. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Test transaction RedoTransaction() error:   *   *******************************************************************/  printf("Test transaction RedoTransaction() error ... ");  tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);  if (!tximpl) {    printf("ERROR: Failed to allocate transaction.\n");    return NS_ERROR_OUT_OF_MEMORY;  }  tx     = 0;  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);  if (NS_FAILED(result)) {    printf("ERROR: QueryInterface() failed for RedoErrorTransaction. (%d)\n",           result);    return result;  }  result = mgr->BeginBatch();  if (NS_FAILED(result)) {    printf("ERROR: BeginBatch() failed. (%d)\n", result);    return result;  }  result = mgr->DoTransaction(tx);  if (NS_FAILED(result)) {    printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);    return result;  }  tx->Release();  result = mgr->EndBatch();  if (NS_FAILED(result)) {    printf("ERROR: EndBatch() failed. (%d)\n", result);    return result;  }  //  // Execute a normal transaction to be used in a later test:  //  tximpl = factory->create(mgr, NONE_FLAG);  if (!tximpl) {    printf("ERROR: Failed to allocate transaction.\n");    return NS_ERROR_OUT_OF_MEMORY;  }  tx     = 0;  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);  if (NS_FAILED(result)) {    printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);    return result;  }  result = mgr->DoTransaction(tx);  if (NS_FAILED(result)) {    printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);    return result;  }  tx->Release();  //  // Undo the 2 transactions just executed.  //  for (i = 1; i <= 2; ++i) {    result = mgr->UndoTransaction();    if (NS_FAILED(result)) {      printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);      return result;    }  }  //  // The RedoErrorTransaction should now be at the top of the redo stack!  //  u1 = u2 = r1 = r2 = 0;  result = mgr->PeekUndoStack(&u1);  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);    return result;  }  result = mgr->PeekRedoStack(&r1);  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);    return result;  }  result = mgr->RedoTransaction();  if (NS_FAILED(result) && result != NS_ERROR_FAILURE) {    printf("ERROR: RedoTransaction() returned unexpected error. (%d)\n", result);    return result;  }  result = mgr->PeekUndoStack(&u2);  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);    return result;  }  if (u1 != u2) {    printf("ERROR: Top of undo stack changed. (%d)\n", result);    return NS_ERROR_FAILURE;  }  result = mgr->PeekRedoStack(&r2);  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!  if (NS_FAILED(result)) {    printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);    return result;  }  if (r1 != r2) {    printf("ERROR: Top of redo stack changed. (%d)\n", result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",           result);    return result;  }  if (numitems != 2) {    printf("ERROR: GetNumberOfUndoItems() expected 2 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on empty redo stack. (%d)\n",           result);    return result;  }  if (numitems != 2) {    printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  printf("passed\n");  /*******************************************************************   *   * Make sure that setting the transaction manager's max transaction   * count to zero, clears both the undo and redo stacks, and executes   * all new commands without pushing them on the undo stack!   *   *******************************************************************/  printf("Test max transaction count of zero ... ");  result = mgr->SetMaxTransactionCount(0);  if (NS_FAILED(result)) {    printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);    return result;  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",           result);    return result;  }  if (numitems != 0) {    printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  for (i = 1; i <= 20; i++) {    tximpl = factory->create(mgr, NONE_FLAG);    if (!tximpl) {      printf("ERROR: Failed to allocate transaction %d.\n", i);      return NS_ERROR_OUT_OF_MEMORY;    }    tx = 0;    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);    if (NS_FAILED(result)) {      printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",             i, result);      return result;    }    result = mgr->BeginBatch();    if (NS_FAILED(result)) {      printf("ERROR: BeginBatch() failed. (%d)\n", result);      return result;    }    result = mgr->DoTransaction(tx);    if (NS_FAILED(result)) {      printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);      return result;    }    tx->Release();    result = mgr->EndBatch();    if (NS_FAILED(result)) {      printf("ERROR: EndBatch() failed. (%d)\n", result);      return result;    }    result = mgr->GetNumberOfUndoItems(&numitems);    if (NS_FAILED(result)) {      printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",             result);      return result;    }    if (numitems != 0) {      printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",             numitems, result);      return NS_ERROR_FAILURE;    }    result = mgr->GetNumberOfRedoItems(&numitems);    if (NS_FAILED(result)) {      printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",             result);      return result;    }    if (numitems != 0) {      printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",             numitems, result);      return NS_ERROR_FAILURE;    }  }  printf("passed\n");  /*******************************************************************   *   * Release the transaction manager. Any transactions on the undo   * and redo stack should automatically be released:   *   *******************************************************************/  printf("Release the transaction manager ... ");  result = mgr->SetMaxTransactionCount(-1);  if (NS_FAILED(result)) {    printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);    return result;  }  // Push 20 transactions on the undo stack:  for (i = 1; i <= 20; i++) {    tximpl = factory->create(mgr, NONE_FLAG);    if (!tximpl) {      printf("ERROR: Failed to allocate transaction %d.\n", i);      return NS_ERROR_OUT_OF_MEMORY;    }    tx = 0;    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);    if (NS_FAILED(result)) {      printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",             i, result);      return result;    }    result = mgr->BeginBatch();    if (NS_FAILED(result)) {      printf("ERROR: BeginBatch() failed. (%d)\n", result);      return result;    }    result = mgr->DoTransaction(tx);    if (NS_FAILED(result)) {      printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);      return result;    }    tx->Release();    result = mgr->EndBatch();    if (NS_FAILED(result)) {      printf("ERROR: EndBatch() failed. (%d)\n", result);      return result;    }    result = mgr->GetNumberOfUndoItems(&numitems);    if (NS_FAILED(result)) {      printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",             result);      return result;    }    if (numitems != i) {      printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",             numitems, result);      return NS_ERROR_FAILURE;    }    result = mgr->GetNumberOfRedoItems(&numitems);    if (NS_FAILED(result)) {      printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",             result);      return result;    }    if (numitems != 0) {      printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",             numitems, result);      return NS_ERROR_FAILURE;    }  }  for (i = 1; i <= 10; i++) {    result = mgr->UndoTransaction();    if (NS_FAILED(result)) {      printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);      return result;    }  }  result = mgr->GetNumberOfUndoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfUndoItems() on empty undo stack with 10 items failed. (%d)\n",           result);    return result;  }  if (numitems != 10) {    printf("ERROR: GetNumberOfUndoItems() expected 10 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->GetNumberOfRedoItems(&numitems);  if (NS_FAILED(result)) {    printf("ERROR: GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",           result);    return result;  }  if (numitems != 10) {    printf("ERROR: GetNumberOfRedoItems() expected 10 got %d. (%d)\n",           numitems, result);    return NS_ERROR_FAILURE;  }  result = mgr->Release();  if (NS_FAILED(result)) {    printf("ERROR: nsITransactionManager Release() failed. (%d)\n", result);    return result;  }  printf("passed\n");  /*******************************************************************   *   * Make sure number of transactions created matches number of   * transactions destroyed!   *   *******************************************************************/  printf("Number of transactions created and destroyed match ... ");  if (sConstructorCount != sDestructorCount) {    printf("ERROR: Transaction constructor count (%d) != destructor count (%d).\n",           sConstructorCount, sDestructorCount);    return NS_ERROR_FAILURE;  }  if (NS_FAILED(result)) {    printf("ERROR: nsITransactionManager Release() failed. (%d)\n", result);    return result;  }  printf("passed\n");  printf("%d transactions processed during quick batch test.\n",         sConstructorCount);  return NS_OK;}