Back to index

lightning-sunbird  0.9+nobinonly
TestTXMgr.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include "nsXPCOM.h"
00041 #include "nsITransactionManager.h"
00042 #include "nsIComponentManager.h"
00043 
00044 static PRInt32 sConstructorCount     = 0;
00045 static PRInt32 sDestructorCount      = 0;
00046 static PRInt32 *sDestructorOrderArr  = 0;
00047 static PRInt32 sDoCount              = 0;
00048 static PRInt32 *sDoOrderArr          = 0;
00049 static PRInt32 sUndoCount            = 0;
00050 static PRInt32 *sUndoOrderArr        = 0;
00051 static PRInt32 sRedoCount            = 0;
00052 static PRInt32 *sRedoOrderArr        = 0;
00053 
00054 // #define ENABLE_DEBUG_PRINTFS 1
00055 
00056 PRInt32 sSimpleTestDestructorOrderArr[] = {
00057           2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,
00058          16,  17,  18,  19,  20,  21,   1,  22,  23,  24,  25,  26,  27,  28,
00059          29,  30,  31,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,
00060          53,  54,  55,  56,  57,  58,  59,  60,  61,  41,  40,  62,  39,  38,
00061          37,  36,  35,  34,  33,  32,  68,  63,  64,  65,  66,  67,  69,  71,
00062          70,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
00063          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
00064          99, 100, 101, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 131,
00065         130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117,
00066         116, 115, 114, 113, 112 };
00067 
00068 PRInt32 sSimpleTestDoOrderArr[] = {
00069           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
00070          15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
00071          29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
00072          43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
00073          57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
00074          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
00075          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
00076          99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
00077         113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
00078         127, 128, 129, 130, 131 };
00079 
00080 PRInt32 sSimpleTestUndoOrderArr[] = {
00081          41,  40,  39,  38,  62,  39,  38,  37,  69,  71,  70, 111, 110, 109,
00082         108, 107, 106, 105, 104, 103, 102, 131, 130, 129, 128, 127, 126, 125,
00083         124, 123, 122 };
00084 
00085 static PRInt32 sSimpleTestRedoOrderArr[] = {
00086          38,  39,  70 };
00087 
00088 PRInt32 sAggregateTestDestructorOrderArr[] = {
00089          14,  13,  12,  11,  10,   9,   8,  21,  20,  19,  18,  17,  16,  15,
00090          28,  27,  26,  25,  24,  23,  22,  35,  34,  33,  32,  31,  30,  29,
00091          42,  41,  40,  39,  38,  37,  36,  49,  48,  47,  46,  45,  44,  43,
00092          56,  55,  54,  53,  52,  51,  50,  63,  62,  61,  60,  59,  58,  57,
00093          70,  69,  68,  67,  66,  65,  64,  77,  76,  75,  74,  73,  72,  71,
00094          84,  83,  82,  81,  80,  79,  78,  91,  90,  89,  88,  87,  86,  85,
00095          98,  97,  96,  95,  94,  93,  92, 105, 104, 103, 102, 101, 100,  99,
00096         112, 111, 110, 109, 108, 107, 106, 119, 118, 117, 116, 115, 114, 113,
00097         126, 125, 124, 123, 122, 121, 120, 133, 132, 131, 130, 129, 128, 127,
00098         140, 139, 138, 137, 136, 135, 134, 147, 146, 145, 144, 143, 142, 141,
00099           7,   6,   5,   4,   3,   2,   1, 154, 153, 152, 151, 150, 149, 148,
00100         161, 160, 159, 158, 157, 156, 155, 168, 167, 166, 165, 164, 163, 162,
00101         175, 174, 173, 172, 171, 170, 169, 182, 181, 180, 179, 178, 177, 176,
00102         189, 188, 187, 186, 185, 184, 183, 196, 195, 194, 193, 192, 191, 190,
00103         203, 202, 201, 200, 199, 198, 197, 210, 209, 208, 207, 206, 205, 204,
00104         217, 216, 215, 214, 213, 212, 211, 294, 293, 292, 291, 290, 289, 288,
00105         301, 300, 299, 298, 297, 296, 295, 308, 307, 306, 305, 304, 303, 302,
00106         315, 314, 313, 312, 311, 310, 309, 322, 321, 320, 319, 318, 317, 316,
00107         329, 328, 327, 326, 325, 324, 323, 336, 335, 334, 333, 332, 331, 330,
00108         343, 342, 341, 340, 339, 338, 337, 350, 349, 348, 347, 346, 345, 344,
00109         357, 356, 355, 354, 353, 352, 351, 364, 363, 362, 361, 360, 359, 358,
00110         371, 370, 369, 368, 367, 366, 365, 378, 377, 376, 375, 374, 373, 372,
00111         385, 384, 383, 382, 381, 380, 379, 392, 391, 390, 389, 388, 387, 386,
00112         399, 398, 397, 396, 395, 394, 393, 406, 405, 404, 403, 402, 401, 400,
00113         413, 412, 411, 410, 409, 408, 407, 420, 419, 418, 417, 416, 415, 414,
00114         427, 426, 425, 424, 423, 422, 421, 287, 286, 285, 284, 283, 282, 281,
00115         280, 279, 278, 277, 276, 275, 274, 434, 433, 432, 431, 430, 429, 428,
00116         273, 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260,
00117         259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246,
00118         245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232,
00119         231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218,
00120         472, 471, 470, 441, 440, 439, 438, 437, 436, 435, 448, 447, 446, 445,
00121         444, 443, 442, 455, 454, 453, 452, 451, 450, 449, 462, 461, 460, 459,
00122         458, 457, 456, 469, 468, 467, 466, 465, 464, 463, 479, 478, 477, 476,
00123         475, 474, 473, 493, 492, 491, 490, 489, 488, 487, 486, 485, 484, 483,
00124         482, 481, 480, 496, 497, 495, 499, 500, 498, 494, 503, 504, 502, 506,
00125         507, 505, 501, 510, 511, 509, 513, 514, 512, 508, 517, 518, 516, 520,
00126         521, 519, 515, 524, 525, 523, 527, 528, 526, 522, 531, 532, 530, 534,
00127         535, 533, 529, 538, 539, 537, 541, 542, 540, 536, 545, 546, 544, 548,
00128         549, 547, 543, 552, 553, 551, 555, 556, 554, 550, 559, 560, 558, 562,
00129         563, 561, 557, 566, 567, 565, 569, 570, 568, 564, 573, 574, 572, 576,
00130         577, 575, 571, 580, 581, 579, 583, 584, 582, 578, 587, 588, 586, 590,
00131         591, 589, 585, 594, 595, 593, 597, 598, 596, 592, 601, 602, 600, 604,
00132         605, 603, 599, 608, 609, 607, 611, 612, 610, 606, 615, 616, 614, 618,
00133         619, 617, 613, 622, 623, 621, 625, 626, 624, 620, 629, 630, 628, 632,
00134         633, 631, 627, 640, 639, 638, 637, 636, 635, 634, 647, 646, 645, 644,
00135         643, 642, 641, 654, 653, 652, 651, 650, 649, 648, 661, 660, 659, 658,
00136         657, 656, 655, 668, 667, 666, 665, 664, 663, 662, 675, 674, 673, 672,
00137         671, 670, 669, 682, 681, 680, 679, 678, 677, 676, 689, 688, 687, 686,
00138         685, 684, 683, 696, 695, 694, 693, 692, 691, 690, 703, 702, 701, 700,
00139         699, 698, 697, 773, 772, 771, 770, 769, 768, 767, 766, 765, 764, 763,
00140         762, 761, 760, 759, 758, 757, 756, 755, 754, 753, 752, 751, 750, 749,
00141         748, 747, 746, 745, 744, 743, 742, 741, 740, 739, 738, 737, 736, 735,
00142         734, 733, 732, 731, 730, 729, 728, 727, 726, 725, 724, 723, 722, 721,
00143         720, 719, 718, 717, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707,
00144         706, 705, 704, 913, 912, 911, 910, 909, 908, 907, 906, 905, 904, 903,
00145         902, 901, 900, 899, 898, 897, 896, 895, 894, 893, 892, 891, 890, 889,
00146         888, 887, 886, 885, 884, 883, 882, 881, 880, 879, 878, 877, 876, 875,
00147         874, 873, 872, 871, 870, 869, 868, 867, 866, 865, 864, 863, 862, 861,
00148         860, 859, 858, 857, 856, 855, 854, 853, 852, 851, 850, 849, 848, 847,
00149         846, 845, 844, 843, 842, 841, 840, 839, 838, 837, 836, 835, 834, 833,
00150         832, 831, 830, 829, 828, 827, 826, 825, 824, 823, 822, 821, 820, 819,
00151         818, 817, 816, 815, 814, 813, 812, 811, 810, 809, 808, 807, 806, 805,
00152         804, 803, 802, 801, 800, 799, 798, 797, 796, 795, 794, 793, 792, 791,
00153         790, 789, 788, 787, 786, 785, 784, 783, 782, 781, 780, 779, 778, 777,
00154         776, 775, 774 };
00155 
00156 PRInt32 sAggregateTestDoOrderArr[] = {
00157           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
00158          15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
00159          29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
00160          43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
00161          57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
00162          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
00163          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
00164          99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
00165         113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
00166         127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
00167         141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
00168         155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
00169         169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
00170         183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
00171         197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
00172         211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
00173         225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
00174         239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
00175         253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
00176         267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
00177         281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
00178         295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
00179         309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
00180         323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
00181         337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
00182         351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
00183         365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
00184         379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392,
00185         393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406,
00186         407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
00187         421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
00188         435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
00189         449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
00190         463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476,
00191         477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
00192         491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504,
00193         505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518,
00194         519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532,
00195         533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546,
00196         547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
00197         561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
00198         575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588,
00199         589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602,
00200         603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616,
00201         617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630,
00202         631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644,
00203         645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658,
00204         659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
00205         673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686,
00206         687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700,
00207         701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714,
00208         715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728,
00209         729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742,
00210         743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756,
00211         757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770,
00212         771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784,
00213         785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798,
00214         799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812,
00215         813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826,
00216         827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840,
00217         841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854,
00218         855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868,
00219         869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882,
00220         883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896,
00221         897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910,
00222         911, 912, 913 };
00223 
00224 PRInt32 sAggregateTestUndoOrderArr[] = {
00225         287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274,
00226         273, 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260,
00227         434, 433, 432, 431, 430, 429, 428, 273, 272, 271, 270, 269, 268, 267,
00228         266, 265, 264, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253,
00229         479, 478, 477, 476, 475, 493, 492, 491, 490, 489, 488, 487, 486, 485,
00230         484, 483, 482, 481, 480, 485, 484, 483, 482, 481, 480, 773, 772, 771,
00231         770, 769, 768, 767, 766, 765, 764, 763, 762, 761, 760, 759, 758, 757,
00232         756, 755, 754, 753, 752, 751, 750, 749, 748, 747, 746, 745, 744, 743,
00233         742, 741, 740, 739, 738, 737, 736, 735, 734, 733, 732, 731, 730, 729,
00234         728, 727, 726, 725, 724, 723, 722, 721, 720, 719, 718, 717, 716, 715,
00235         714, 713, 712, 711, 710, 709, 708, 707, 706, 705, 704, 913, 912, 911,
00236         910, 909, 908, 907, 906, 905, 904, 903, 902, 901, 900, 899, 898, 897,
00237         896, 895, 894, 893, 892, 891, 890, 889, 888, 887, 886, 885, 884, 883,
00238         882, 881, 880, 879, 878, 877, 876, 875, 874, 873, 872, 871, 870, 869,
00239         868, 867, 866, 865, 864, 863, 862, 861, 860, 859, 858, 857, 856, 855,
00240         854, 853, 852, 851, 850, 849, 848, 847, 846, 845, 844 };
00241 
00242 PRInt32 sAggregateTestRedoOrderArr[] = {
00243         260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
00244         476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486 };
00245 
00246 PRInt32 sSimpleBatchTestDestructorOrderArr[] = {
00247          21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,
00248          35,  36,  37,  38,  39,  40,  43,  42,  41,  64,  63,  62,  61,  60,
00249          59,  58,  57,  56,  55,  54,  53,  52,  51,  50,  49,  48,  47,  46,
00250          45,  44,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,  10,   9,
00251           8,   7,   6,   5,   4,   3,   2,   1,  65,  67,  66,  68,  69,  70,
00252          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
00253          85,  86,  87, 107, 106, 105, 104, 103, 102, 101, 100,  99,  98,  97,
00254          96,  95,  94,  93,  92,  91,  90,  89,  88 };
00255 
00256 PRInt32 sSimpleBatchTestDoOrderArr[] = {
00257           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
00258          15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
00259          29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
00260          43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
00261          57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
00262          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
00263          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
00264          99, 100, 101, 102, 103, 104, 105, 106, 107 };
00265 
00266 PRInt32 sSimpleBatchTestUndoOrderArr[] = {
00267          43,  42,  41,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,  10,
00268           9,   8,   7,   6,   5,   4,   3,   2,   1,  43,  42,  41,  63,  62,
00269          61,  60,  59,  58,  57,  56,  55,  54,  53,  52,  51,  50,  49,  48,
00270          47,  46,  45,  44,  65,  67,  66, 107, 106, 105, 104, 103, 102, 101,
00271         100,  99,  98 };
00272 
00273 PRInt32 sSimpleBatchTestRedoOrderArr[] = {
00274           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
00275          15,  16,  17,  18,  19,  20,  41,  42,  43,  66 };
00276 
00277 PRInt32 sAggregateBatchTestDestructorOrderArr[] = {
00278         147, 146, 145, 144, 143, 142, 141, 154, 153, 152, 151, 150, 149, 148,
00279         161, 160, 159, 158, 157, 156, 155, 168, 167, 166, 165, 164, 163, 162,
00280         175, 174, 173, 172, 171, 170, 169, 182, 181, 180, 179, 178, 177, 176,
00281         189, 188, 187, 186, 185, 184, 183, 196, 195, 194, 193, 192, 191, 190,
00282         203, 202, 201, 200, 199, 198, 197, 210, 209, 208, 207, 206, 205, 204,
00283         217, 216, 215, 214, 213, 212, 211, 224, 223, 222, 221, 220, 219, 218,
00284         231, 230, 229, 228, 227, 226, 225, 238, 237, 236, 235, 234, 233, 232,
00285         245, 244, 243, 242, 241, 240, 239, 252, 251, 250, 249, 248, 247, 246,
00286         259, 258, 257, 256, 255, 254, 253, 266, 265, 264, 263, 262, 261, 260,
00287         273, 272, 271, 270, 269, 268, 267, 280, 279, 278, 277, 276, 275, 274,
00288         301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288,
00289         287, 286, 285, 284, 283, 282, 281, 444, 443, 442, 441, 440, 439, 438,
00290         437, 436, 435, 434, 433, 432, 431, 430, 429, 428, 427, 426, 425, 424,
00291         423, 422, 421, 420, 419, 418, 417, 416, 415, 414, 413, 412, 411, 410,
00292         409, 408, 407, 406, 405, 404, 403, 402, 401, 400, 399, 398, 397, 396,
00293         395, 394, 393, 392, 391, 390, 389, 388, 387, 386, 385, 384, 383, 382,
00294         381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 370, 369, 368,
00295         367, 366, 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, 354,
00296         353, 352, 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340,
00297         339, 338, 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326,
00298         325, 324, 323, 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, 312,
00299         311, 310, 309, 308, 307, 306, 305, 304, 303, 302, 140, 139, 138, 137,
00300         136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123,
00301         122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109,
00302         108, 107, 106, 105, 104, 103, 102, 101, 100,  99,  98,  97,  96,  95,
00303          94,  93,  92,  91,  90,  89,  88,  87,  86,  85,  84,  83,  82,  81,
00304          80,  79,  78,  77,  76,  75,  74,  73,  72,  71,  70,  69,  68,  67,
00305          66,  65,  64,  63,  62,  61,  60,  59,  58,  57,  56,  55,  54,  53,
00306          52,  51,  50,  49,  48,  47,  46,  45,  44,  43,  42,  41,  40,  39,
00307          38,  37,  36,  35,  34,  33,  32,  31,  30,  29,  28,  27,  26,  25,
00308          24,  23,  22,  21,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,
00309          10,   9,   8,   7,   6,   5,   4,   3,   2,   1, 451, 450, 449, 448,
00310         447, 446, 445, 465, 464, 463, 462, 461, 460, 459, 458, 457, 456, 455,
00311         454, 453, 452, 468, 469, 467, 471, 472, 470, 466, 475, 476, 474, 478,
00312         479, 477, 473, 482, 483, 481, 485, 486, 484, 480, 489, 490, 488, 492,
00313         493, 491, 487, 496, 497, 495, 499, 500, 498, 494, 503, 504, 502, 506,
00314         507, 505, 501, 510, 511, 509, 513, 514, 512, 508, 517, 518, 516, 520,
00315         521, 519, 515, 524, 525, 523, 527, 528, 526, 522, 531, 532, 530, 534,
00316         535, 533, 529, 538, 539, 537, 541, 542, 540, 536, 545, 546, 544, 548,
00317         549, 547, 543, 552, 553, 551, 555, 556, 554, 550, 559, 560, 558, 562,
00318         563, 561, 557, 566, 567, 565, 569, 570, 568, 564, 573, 574, 572, 576,
00319         577, 575, 571, 580, 581, 579, 583, 584, 582, 578, 587, 588, 586, 590,
00320         591, 589, 585, 594, 595, 593, 597, 598, 596, 592, 601, 602, 600, 604,
00321         605, 603, 599, 745, 744, 743, 742, 741, 740, 739, 738, 737, 736, 735,
00322         734, 733, 732, 731, 730, 729, 728, 727, 726, 725, 724, 723, 722, 721,
00323         720, 719, 718, 717, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707,
00324         706, 705, 704, 703, 702, 701, 700, 699, 698, 697, 696, 695, 694, 693,
00325         692, 691, 690, 689, 688, 687, 686, 685, 684, 683, 682, 681, 680, 679,
00326         678, 677, 676, 675, 674, 673, 672, 671, 670, 669, 668, 667, 666, 665,
00327         664, 663, 662, 661, 660, 659, 658, 657, 656, 655, 654, 653, 652, 651,
00328         650, 649, 648, 647, 646, 645, 644, 643, 642, 641, 640, 639, 638, 637,
00329         636, 635, 634, 633, 632, 631, 630, 629, 628, 627, 626, 625, 624, 623,
00330         622, 621, 620, 619, 618, 617, 616, 615, 614, 613, 612, 611, 610, 609,
00331         608, 607, 606 };
00332 
00333 PRInt32 sAggregateBatchTestDoOrderArr[] = {
00334           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
00335          15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
00336          29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
00337          43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
00338          57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
00339          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
00340          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
00341          99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
00342         113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
00343         127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
00344         141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
00345         155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
00346         169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
00347         183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
00348         197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
00349         211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
00350         225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
00351         239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
00352         253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
00353         267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
00354         281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
00355         295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
00356         309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
00357         323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
00358         337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
00359         351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
00360         365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
00361         379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392,
00362         393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406,
00363         407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
00364         421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
00365         435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
00366         449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
00367         463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476,
00368         477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
00369         491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504,
00370         505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518,
00371         519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532,
00372         533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546,
00373         547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
00374         561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
00375         575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588,
00376         589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602,
00377         603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616,
00378         617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630,
00379         631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644,
00380         645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658,
00381         659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
00382         673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686,
00383         687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700,
00384         701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714,
00385         715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728,
00386         729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742,
00387         743, 744, 745 };
00388 
00389 PRInt32 sAggregateBatchTestUndoOrderArr[] = {
00390         301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288,
00391         287, 286, 285, 284, 283, 282, 281, 140, 139, 138, 137, 136, 135, 134,
00392         133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120,
00393         119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106,
00394         105, 104, 103, 102, 101, 100,  99,  98,  97,  96,  95,  94,  93,  92,
00395          91,  90,  89,  88,  87,  86,  85,  84,  83,  82,  81,  80,  79,  78,
00396          77,  76,  75,  74,  73,  72,  71,  70,  69,  68,  67,  66,  65,  64,
00397          63,  62,  61,  60,  59,  58,  57,  56,  55,  54,  53,  52,  51,  50,
00398          49,  48,  47,  46,  45,  44,  43,  42,  41,  40,  39,  38,  37,  36,
00399          35,  34,  33,  32,  31,  30,  29,  28,  27,  26,  25,  24,  23,  22,
00400          21,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,  10,   9,   8,
00401           7,   6,   5,   4,   3,   2,   1, 301, 300, 299, 298, 297, 296, 295,
00402         294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281,
00403         441, 440, 439, 438, 437, 436, 435, 434, 433, 432, 431, 430, 429, 428,
00404         427, 426, 425, 424, 423, 422, 421, 420, 419, 418, 417, 416, 415, 414,
00405         413, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, 400,
00406         399, 398, 397, 396, 395, 394, 393, 392, 391, 390, 389, 388, 387, 386,
00407         385, 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372,
00408         371, 370, 369, 368, 367, 366, 365, 364, 363, 362, 361, 360, 359, 358,
00409         357, 356, 355, 354, 353, 352, 351, 350, 349, 348, 347, 346, 345, 344,
00410         343, 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, 331, 330,
00411         329, 328, 327, 326, 325, 324, 323, 322, 321, 320, 319, 318, 317, 316,
00412         315, 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, 304, 303, 302,
00413         451, 450, 449, 448, 447, 465, 464, 463, 462, 461, 460, 459, 458, 457,
00414         456, 455, 454, 453, 452, 457, 456, 455, 454, 453, 452, 745, 744, 743,
00415         742, 741, 740, 739, 738, 737, 736, 735, 734, 733, 732, 731, 730, 729,
00416         728, 727, 726, 725, 724, 723, 722, 721, 720, 719, 718, 717, 716, 715,
00417         714, 713, 712, 711, 710, 709, 708, 707, 706, 705, 704, 703, 702, 701,
00418         700, 699, 698, 697, 696, 695, 694, 693, 692, 691, 690, 689, 688, 687,
00419         686, 685, 684, 683, 682, 681, 680, 679, 678, 677, 676 };
00420 
00421 PRInt32 sAggregateBatchTestRedoOrderArr[] = {
00422           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
00423          15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
00424          29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
00425          43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
00426          57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
00427          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
00428          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
00429          99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
00430         113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
00431         127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
00432         281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
00433         295, 296, 297, 298, 299, 300, 301, 448, 449, 450, 451, 452, 453, 454,
00434         455, 456, 457, 458 };
00435 
00436 #define TEST_TXMGR_IF_RELEASE(tx) if (tx) tx->Release(); // Release but don't clear pointer!
00437 
00438 class TestTransaction : public nsITransaction
00439 {
00440 public:
00441 
00442   TestTransaction() { }
00443   virtual ~TestTransaction()     {}
00444 
00445   NS_DECL_ISUPPORTS
00446 };
00447 
00448 NS_IMPL_ISUPPORTS1(TestTransaction, nsITransaction)
00449 
00450 class SimpleTransaction : public TestTransaction
00451 {
00452 public:
00453 
00454 #define NONE_FLAG               0
00455 #define THROWS_DO_ERROR_FLAG    1
00456 #define THROWS_UNDO_ERROR_FLAG  2
00457 #define THROWS_REDO_ERROR_FLAG  4
00458 #define MERGE_FLAG              8
00459 #define TRANSIENT_FLAG         16
00460 #define BATCH_FLAG             32
00461 #define ALL_ERROR_FLAGS        (THROWS_DO_ERROR_FLAG|THROWS_UNDO_ERROR_FLAG|THROWS_REDO_ERROR_FLAG)
00462 
00463   PRInt32 mVal;
00464   PRInt32 mFlags;
00465 
00466   SimpleTransaction(PRInt32 aFlags=NONE_FLAG)
00467                     : mVal(++sConstructorCount), mFlags(aFlags)
00468   {}
00469 
00470   virtual ~SimpleTransaction()
00471   {
00472     //
00473     // Make sure transactions are being destroyed in the order we expect!
00474     // Notice that we don't check to see if we go past the end of the array.
00475     // This is done on purpose since we want to crash if the order array is out
00476     // of date.
00477     //
00478     if (sDestructorOrderArr && mVal != sDestructorOrderArr[sDestructorCount]) {
00479       printf("ERROR: ~SimpleTransaction expected %d got %d.\n",
00480              mVal, sDestructorOrderArr[sDestructorCount]);
00481       exit(NS_ERROR_FAILURE);
00482     }
00483 
00484     ++sDestructorCount;
00485 
00486 #ifdef ENABLE_DEBUG_PRINTFS
00487     printf("\n~SimpleTransaction: %d - 0x%.8x\n", mVal, (PRInt32)this);
00488 #endif // ENABLE_DEBUG_PRINTFS
00489 
00490     mVal = -1;
00491   }
00492 
00493   NS_IMETHOD DoTransaction()
00494   {
00495     //
00496     // Make sure DoTransaction() is called in the order we expect!
00497     // Notice that we don't check to see if we go past the end of the array.
00498     // This is done on purpose since we want to crash if the order array is out
00499     // of date.
00500     //
00501     if (sDoOrderArr && mVal != sDoOrderArr[sDoCount]) {
00502       printf("ERROR: ~SimpleTransaction expected %d got %d.\n",
00503              mVal, sDoOrderArr[sDoCount]);
00504       exit(NS_ERROR_FAILURE);
00505     }
00506 
00507     ++sDoCount;
00508 
00509 #ifdef ENABLE_DEBUG_PRINTFS
00510     printf("\nSimpleTransaction.DoTransaction: %d - 0x%.8x\n", mVal, (PRInt32)this);
00511 #endif // ENABLE_DEBUG_PRINTFS
00512 
00513     return (mFlags & THROWS_DO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
00514   }
00515 
00516   NS_IMETHOD UndoTransaction()
00517   {
00518     //
00519     // Make sure UndoTransaction() is called in the order we expect!
00520     // Notice that we don't check to see if we go past the end of the array.
00521     // This is done on purpose since we want to crash if the order array is out
00522     // of date.
00523     //
00524     if (sUndoOrderArr && mVal != sUndoOrderArr[sUndoCount]) {
00525       printf("ERROR: ~SimpleTransaction expected %d got %d.\n",
00526              mVal, sUndoOrderArr[sUndoCount]);
00527       exit(NS_ERROR_FAILURE);
00528     }
00529 
00530     ++sUndoCount;
00531 
00532 #ifdef ENABLE_DEBUG_PRINTFS
00533     printf("\nSimpleTransaction.Undo: %d - 0x%.8x\n", mVal, (PRInt32)this);
00534 #endif // ENABLE_DEBUG_PRINTFS
00535 
00536     return (mFlags & THROWS_UNDO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
00537   }
00538 
00539   NS_IMETHOD RedoTransaction()
00540   {
00541     //
00542     // Make sure RedoTransaction() is called in the order we expect!
00543     // Notice that we don't check to see if we go past the end of the array.
00544     // This is done on purpose since we want to crash if the order array is out
00545     // of date.
00546     //
00547     if (sRedoOrderArr && mVal != sRedoOrderArr[sRedoCount]) {
00548       printf("ERROR: ~SimpleTransaction expected %d got %d.\n",
00549              mVal, sRedoOrderArr[sRedoCount]);
00550       exit(NS_ERROR_FAILURE);
00551     }
00552 
00553     ++sRedoCount;
00554 
00555 #ifdef ENABLE_DEBUG_PRINTFS
00556     printf("\nSimpleTransaction.Redo: %d - 0x%.8x\n", mVal, (PRInt32)this);
00557 #endif // ENABLE_DEBUG_PRINTFS
00558 
00559     return (mFlags & THROWS_REDO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
00560   }
00561 
00562   NS_IMETHOD GetIsTransient(PRBool *aIsTransient)
00563   {
00564     if (aIsTransient)
00565       *aIsTransient = (mFlags & TRANSIENT_FLAG) ? PR_TRUE : PR_FALSE;
00566 
00567     return NS_OK;
00568   }
00569 
00570   NS_IMETHOD Merge(nsITransaction *aTransaction, PRBool *aDidMerge) 
00571   {
00572     if (aDidMerge)
00573       *aDidMerge = (mFlags & MERGE_FLAG) ? PR_TRUE : PR_FALSE;
00574 
00575     return NS_OK;
00576   }
00577 };
00578 
00579 class AggregateTransaction : public SimpleTransaction
00580 {
00581 private:
00582 
00583   AggregateTransaction(nsITransactionManager *aTXMgr, PRInt32 aLevel,
00584                        PRInt32 aNumber, PRInt32 aMaxLevel,
00585                        PRInt32 aNumChildrenPerNode,
00586                        PRInt32 aFlags)
00587   {
00588     mLevel              = aLevel;
00589     mNumber             = aNumber;
00590     mTXMgr              = aTXMgr;
00591     mFlags              = aFlags & (~ALL_ERROR_FLAGS);
00592     mErrorFlags         = aFlags & ALL_ERROR_FLAGS;
00593     mTXMgr              = aTXMgr;
00594     mMaxLevel           = aMaxLevel;
00595     mNumChildrenPerNode = aNumChildrenPerNode;
00596   }
00597 
00598 
00599 public:
00600   nsITransactionManager *mTXMgr;
00601 
00602   PRInt32 mLevel;
00603   PRInt32 mNumber;
00604   PRInt32 mErrorFlags;
00605 
00606   PRInt32 mMaxLevel;
00607   PRInt32 mNumChildrenPerNode;
00608 
00609   AggregateTransaction(nsITransactionManager *aTXMgr,
00610                        PRInt32 aMaxLevel, PRInt32 aNumChildrenPerNode,
00611                        PRInt32 aFlags=NONE_FLAG)
00612   {
00613     mLevel              = 1;
00614     mNumber             = 1;
00615     mFlags              = aFlags & (~ALL_ERROR_FLAGS);
00616     mErrorFlags         = aFlags & ALL_ERROR_FLAGS;
00617     mTXMgr              = aTXMgr;
00618     mMaxLevel           = aMaxLevel;
00619     mNumChildrenPerNode = aNumChildrenPerNode;
00620   }
00621 
00622   virtual ~AggregateTransaction()
00623   {
00624     // printf("~AggregateTransaction(0x%.8x) - %3d (%3d)\n", this, mLevel, mVal);
00625   }
00626 
00627   NS_IMETHOD DoTransaction()
00628   {
00629     if (mLevel >= mMaxLevel) {
00630       // Only leaf nodes can throw errors!
00631       mFlags |= mErrorFlags;
00632     }
00633 
00634     nsresult result = SimpleTransaction::DoTransaction();
00635 
00636     if (NS_FAILED(result)) {
00637       // printf("ERROR: QueryInterface() failed for transaction level %d. (%d)\n",
00638       //       mLevel, result);
00639       return result;
00640     }
00641 
00642     if (mLevel >= mMaxLevel)
00643       return NS_OK;
00644 
00645     if (mFlags & BATCH_FLAG) {
00646       result = mTXMgr->BeginBatch();
00647       if (NS_FAILED(result)) {
00648         return result;
00649       }
00650     }
00651 
00652     PRInt32 cLevel = mLevel + 1;
00653 
00654     for (int i = 1; i <= mNumChildrenPerNode; i++) {
00655       PRInt32 flags = mErrorFlags & THROWS_DO_ERROR_FLAG;
00656 
00657       if ((mErrorFlags & THROWS_REDO_ERROR_FLAG) && i == mNumChildrenPerNode) {
00658         // Make the rightmost leaf transaction throw the error!
00659         flags = THROWS_REDO_ERROR_FLAG;
00660         mErrorFlags = mErrorFlags & (~THROWS_REDO_ERROR_FLAG);
00661       }
00662       else if ((mErrorFlags & THROWS_UNDO_ERROR_FLAG)
00663                && i == 1) {
00664         // Make the leftmost leaf transaction throw the error!
00665         flags = THROWS_UNDO_ERROR_FLAG;
00666         mErrorFlags = mErrorFlags & (~THROWS_UNDO_ERROR_FLAG);
00667       }
00668 
00669       flags |= mFlags & BATCH_FLAG;
00670 
00671       AggregateTransaction *tximpl =
00672               new AggregateTransaction(mTXMgr, cLevel, i, mMaxLevel,
00673                                        mNumChildrenPerNode, flags);
00674 
00675       if (!tximpl) {
00676         printf("ERROR: Failed to allocate AggregateTransaction %d, level %d. (%d)\n",
00677                i, mLevel, result);
00678 
00679         if (mFlags & BATCH_FLAG)
00680           mTXMgr->EndBatch();
00681 
00682         return NS_ERROR_OUT_OF_MEMORY;
00683       }
00684 
00685       nsITransaction *tx = 0;
00686       result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
00687       if (NS_FAILED(result)) {
00688         printf("ERROR: QueryInterface() failed for transaction %d, level %d. (%d)\n",
00689                i, mLevel, result);
00690 
00691         if (mFlags & BATCH_FLAG)
00692           mTXMgr->EndBatch();
00693 
00694         return result;
00695       }
00696 
00697       result = mTXMgr->DoTransaction(tx);
00698 
00699       if (NS_FAILED(result)) {
00700         // printf("ERROR: Failed to execute transaction %d, level %d. (%d)\n",
00701         //        i, mLevel, result);
00702         tx->Release();
00703 
00704         if (mFlags & BATCH_FLAG)
00705           mTXMgr->EndBatch();
00706 
00707         return result;
00708       }
00709 
00710       tx->Release();
00711     }
00712 
00713     if (mFlags & BATCH_FLAG)
00714       mTXMgr->EndBatch();
00715 
00716     return result;
00717   }
00718 };
00719 
00720 class TestTransactionFactory
00721 {
00722 public:
00723   virtual TestTransaction *create(nsITransactionManager *txmgr, PRInt32 flags) = 0;
00724 };
00725 
00726 class SimpleTransactionFactory : public TestTransactionFactory
00727 {
00728 public:
00729 
00730   TestTransaction *create(nsITransactionManager *txmgr, PRInt32 flags)
00731   {
00732     return (TestTransaction *)new SimpleTransaction(flags);
00733   }
00734 };
00735 
00736 class AggregateTransactionFactory : public TestTransactionFactory
00737 {
00738 public:
00739 
00740   PRInt32 mMaxLevel;
00741   PRInt32 mNumChildrenPerNode;
00742   PRInt32 mFixedFlags;
00743 
00744   AggregateTransactionFactory(PRInt32 aMaxLevel, PRInt32 aNumChildrenPerNode,
00745                               PRInt32 aFixedFlags=NONE_FLAG)
00746       : mMaxLevel(aMaxLevel), mNumChildrenPerNode(aNumChildrenPerNode),
00747         mFixedFlags(aFixedFlags)
00748   {
00749   }
00750 
00751   virtual TestTransaction *create(nsITransactionManager *txmgr, PRInt32 flags)
00752   {
00753     return (TestTransaction *)new AggregateTransaction(txmgr, mMaxLevel,
00754                                                        mNumChildrenPerNode,
00755                                                        flags | mFixedFlags);
00756   }
00757 };
00758 
00759 void
00760 reset_globals()
00761 {
00762   sConstructorCount   = 0;
00763 
00764   sDestructorCount    = 0;
00765   sDestructorOrderArr = 0;
00766 
00767   sDoCount            = 0;
00768   sDoOrderArr         = 0;
00769 
00770   sUndoCount          = 0;
00771   sUndoOrderArr       = 0;
00772 
00773   sRedoCount          = 0;
00774   sRedoOrderArr       = 0;
00775 }
00776 
00777 nsresult
00778 quick_test(TestTransactionFactory *factory)
00779 {
00780   /*******************************************************************
00781    *
00782    * Create a transaction manager implementation:
00783    *
00784    *******************************************************************/
00785 
00786   printf("Create transaction manager instance ... ");
00787 
00788   PRInt32 i, numitems = 0;
00789   nsCOMPtr<nsITransactionManager> mgr;
00790   nsITransaction  *tx        = 0;
00791   TestTransaction *tximpl    = 0;
00792   nsITransaction *u1 = 0, *u2 = 0;
00793   nsITransaction *r1 = 0, *r2 = 0;
00794   nsresult result;
00795 
00796   mgr = do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
00797   if (NS_FAILED(result) || !mgr) {
00798     printf("ERROR: Failed to create Transaction Manager instance.\n");
00799     return NS_ERROR_OUT_OF_MEMORY;
00800   }
00801 
00802   printf("passed\n");
00803 
00804   /*******************************************************************
00805    *
00806    * Call DoTransaction() with a null transaction:
00807    *
00808    *******************************************************************/
00809 
00810   printf("Call DoTransaction() with null transaction ... ");
00811   result = mgr->DoTransaction(0);
00812 
00813   if (NS_FAILED(result)
00814       && result != NS_ERROR_NULL_POINTER) {
00815     printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);
00816     return result;
00817   }
00818 
00819   printf("passed\n");
00820 
00821   /*******************************************************************
00822    *
00823    * Call UndoTransaction() with an empty undo stack:
00824    *
00825    *******************************************************************/
00826 
00827   printf("Call UndoTransaction() with empty undo stack ... ");
00828   result = mgr->UndoTransaction();
00829 
00830   if (NS_FAILED(result)) {
00831     printf("ERROR: Undo on empty undo stack failed. (%d)\n", result);
00832     return result;
00833   }
00834 
00835   printf("passed\n");
00836 
00837   /*******************************************************************
00838    *
00839    * Call RedoTransaction() with an empty redo stack:
00840    *
00841    *******************************************************************/
00842 
00843   printf("Call RedoTransaction() with empty redo stack ... ");
00844   result = mgr->RedoTransaction();
00845 
00846   if (NS_FAILED(result)) {
00847     printf("ERROR: Redo on empty redo stack failed. (%d)\n", result);
00848     return result;
00849   }
00850 
00851   printf("passed\n");
00852 
00853   /*******************************************************************
00854    *
00855    * Call SetMaxTransactionCount(-1) with empty undo and redo stacks:
00856    *
00857    *******************************************************************/
00858 
00859   printf("Call SetMaxTransactionCount(-1) with empty undo and redo stacks ... ");
00860   result = mgr->SetMaxTransactionCount(-1);
00861 
00862   if (NS_FAILED(result)) {
00863     printf("ERROR: SetMaxTransactionCount(-1) failed. (%d)\n", result);
00864     return result;
00865   }
00866 
00867   printf("passed\n");
00868 
00869   /*******************************************************************
00870    *
00871    * Call SetMaxTransactionCount(0) with empty undo and redo stacks:
00872    *
00873    *******************************************************************/
00874 
00875   printf("Call SetMaxTransactionCount(0) with empty undo and redo stacks ... ");
00876   result = mgr->SetMaxTransactionCount(0);
00877 
00878   if (NS_FAILED(result)) {
00879     printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);
00880     return result;
00881   }
00882 
00883   printf("passed\n");
00884 
00885   /*******************************************************************
00886    *
00887    * Call SetMaxTransactionCount(10) with empty undo and redo stacks:
00888    *
00889    *******************************************************************/
00890 
00891   printf("Call SetMaxTransactionCount(10) with empty undo and redo stacks ... ");
00892   result = mgr->SetMaxTransactionCount(10);
00893 
00894   if (NS_FAILED(result)) {
00895     printf("ERROR: SetMaxTransactionCount(10) failed. (%d)\n", result);
00896     return result;
00897   }
00898 
00899   printf("passed\n");
00900 
00901   /*******************************************************************
00902    *
00903    * Call Clear() with empty undo and redo stacks:
00904    *
00905    *******************************************************************/
00906 
00907   printf("Call Clear() with empty undo and redo stack ... ");
00908   result = mgr->Clear();
00909 
00910   if (NS_FAILED(result)) {
00911     printf("ERROR: Clear on empty undo and redo stack failed. (%d)\n", result);
00912     return result;
00913   }
00914 
00915   printf("passed\n");
00916 
00917   /*******************************************************************
00918    *
00919    * Call GetNumberOfUndoItems() with an empty undo stack:
00920    *
00921    *******************************************************************/
00922 
00923   numitems = 0;
00924 
00925   printf("Call GetNumberOfUndoItems() with empty undo stack ... ");
00926   result = mgr->GetNumberOfUndoItems(&numitems);
00927 
00928   if (NS_FAILED(result)) {
00929     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
00930            result);
00931     return result;
00932   }
00933 
00934   if (numitems != 0) {
00935     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
00936            numitems, result);
00937     return NS_ERROR_FAILURE;
00938   }
00939 
00940   printf("passed\n");
00941 
00942   /*******************************************************************
00943    *
00944    * Call GetNumberOfRedoItems() with an empty redo stack:
00945    *
00946    *******************************************************************/
00947 
00948   printf("Call GetNumberOfRedoItems() with empty redo stack ... ");
00949   result = mgr->GetNumberOfRedoItems(&numitems);
00950 
00951   if (NS_FAILED(result)) {
00952     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
00953            result);
00954     return result;
00955   }
00956 
00957   if (numitems != 0) {
00958     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
00959            numitems, result);
00960     return NS_ERROR_FAILURE;
00961   }
00962 
00963   printf("passed\n");
00964 
00965   /*******************************************************************
00966    *
00967    * Call PeekUndoStack() with an empty undo stack:
00968    *
00969    *******************************************************************/
00970 
00971   printf("Call PeekUndoStack() with empty undo stack ... ");
00972 
00973   tx = 0;
00974   result = mgr->PeekUndoStack(&tx);
00975 
00976   TEST_TXMGR_IF_RELEASE(tx); // Don't hold onto any references!
00977 
00978   if (NS_FAILED(result)) {
00979     printf("ERROR: PeekUndoStack() on empty undo stack failed. (%d)\n", result);
00980     return result;
00981   }
00982 
00983   if (tx != 0) {
00984     printf("ERROR: PeekUndoStack() on empty undo stack failed. (%d)\n", result);
00985     return NS_ERROR_FAILURE;
00986   }
00987 
00988   printf("passed\n");
00989 
00990   /*******************************************************************
00991    *
00992    * Call PeekRedoStack() with an empty undo stack:
00993    *
00994    *******************************************************************/
00995 
00996   printf("Call PeekRedoStack() with empty undo stack ... ");
00997 
00998   tx = 0;
00999   result = mgr->PeekRedoStack(&tx);
01000 
01001   TEST_TXMGR_IF_RELEASE(tx); // Don't hold onto any references!
01002 
01003   if (NS_FAILED(result)) {
01004     printf("ERROR: PeekRedoStack() on empty redo stack failed. (%d)\n", result);
01005     return result;
01006   }
01007 
01008   if (tx != 0) {
01009     printf("ERROR: PeekRedoStack() on empty redo stack failed. (%d)\n", result);
01010     return NS_ERROR_FAILURE;
01011   }
01012 
01013   printf("passed\n");
01014 
01015   /*******************************************************************
01016    *
01017    * Call AddListener() with a null listener pointer:
01018    *
01019    *******************************************************************/
01020 
01021   printf("Call AddListener() with null listener ... ");
01022 
01023   result = mgr->AddListener(0);
01024 
01025   if (NS_FAILED(result)
01026       && result != NS_ERROR_NULL_POINTER) {
01027     printf("ERROR: AddListener() returned unexpected error. (%d)\n", result);
01028     return result;
01029   }
01030 
01031   printf("passed\n");
01032 
01033   /*******************************************************************
01034    *
01035    * Call RemoveListener() with a null listener pointer:
01036    *
01037    *******************************************************************/
01038 
01039   printf("Call RemoveListener() with null listener ... ");
01040 
01041   result = mgr->RemoveListener(0);
01042 
01043   if (NS_FAILED(result)
01044       && result != NS_ERROR_NULL_POINTER) {
01045     printf("ERROR: RemoveListener() returned unexpected error. (%d)\n", result);
01046     return result;
01047   }
01048 
01049   printf("passed\n");
01050 
01051   /*******************************************************************
01052    *
01053    * Test coalescing by executing a transaction that can merge any
01054    * command into itself. Then execute 20 transaction. Afterwards,
01055    * we should still have the first transaction sitting on the undo
01056    * stack.
01057    *
01058    *******************************************************************/
01059 
01060   printf("Test coalescing of transactions ... ");
01061 
01062   result = mgr->SetMaxTransactionCount(10);
01063 
01064   if (NS_FAILED(result)) {
01065     printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);
01066     return result;
01067   }
01068 
01069 
01070   tximpl = factory->create(mgr, MERGE_FLAG);
01071 
01072   if (!tximpl) {
01073     printf("ERROR: Failed to allocate initial transaction.\n");
01074     return NS_ERROR_OUT_OF_MEMORY;
01075   }
01076 
01077   tx = 0;
01078 
01079   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
01080 
01081   if (NS_FAILED(result)) {
01082     printf("ERROR: QueryInterface() failed for initial transaction. (%d)\n",
01083            result);
01084     return result;
01085   }
01086 
01087   result = mgr->DoTransaction(tx);
01088 
01089   if (NS_FAILED(result)) {
01090     printf("ERROR: Failed to execute initial transaction. (%d)\n", result);
01091     return result;
01092   }
01093 
01094   tx->Release();
01095 
01096   u1 = u2 = r1 = r2 = 0;
01097 
01098   result = mgr->PeekUndoStack(&u1);
01099 
01100   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
01101 
01102   if (NS_FAILED(result)) {
01103     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
01104     return result;
01105   }
01106 
01107   if (u1 != tx) {
01108     printf("ERROR: Top of undo stack is different!. (%d)\n", result);
01109     return NS_ERROR_FAILURE;
01110   }
01111 
01112   result = mgr->PeekRedoStack(&r1);
01113 
01114   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
01115 
01116   if (NS_FAILED(result)) {
01117     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
01118     return result;
01119   }
01120 
01121   for (i = 1; i <= 20; i++) {
01122     tximpl = factory->create(mgr, NONE_FLAG);
01123 
01124     if (!tximpl) {
01125       printf("ERROR: Failed to allocate transaction %d.\n", i);
01126       return NS_ERROR_OUT_OF_MEMORY;
01127     }
01128 
01129     tx = 0;
01130     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
01131     if (NS_FAILED(result)) {
01132       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
01133              i, result);
01134       return result;
01135     }
01136 
01137     result = mgr->DoTransaction(tx);
01138     if (NS_FAILED(result)) {
01139       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
01140       return result;
01141     }
01142 
01143     tx->Release();
01144   }
01145 
01146   result = mgr->PeekUndoStack(&u2);
01147 
01148   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
01149 
01150   if (NS_FAILED(result)) {
01151     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
01152     return result;
01153   }
01154 
01155   if (u1 != u2) {
01156     printf("ERROR: Top of undo stack changed. (%d)\n", result);
01157     return NS_ERROR_FAILURE;
01158   }
01159 
01160   result = mgr->PeekRedoStack(&r2);
01161 
01162   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
01163 
01164   if (NS_FAILED(result)) {
01165     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
01166     return result;
01167   }
01168 
01169   if (r1 != r2) {
01170     printf("ERROR: Top of redo stack changed. (%d)\n", result);
01171     return NS_ERROR_FAILURE;
01172   }
01173 
01174   result = mgr->GetNumberOfUndoItems(&numitems);
01175 
01176   if (NS_FAILED(result)) {
01177     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
01178            result);
01179     return result;
01180   }
01181 
01182   if (numitems != 1) {
01183     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
01184            numitems, result);
01185     return NS_ERROR_FAILURE;
01186   }
01187 
01188   result = mgr->GetNumberOfRedoItems(&numitems);
01189 
01190   if (NS_FAILED(result)) {
01191     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
01192            result);
01193     return result;
01194   }
01195 
01196   if (numitems != 0) {
01197     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
01198            numitems, result);
01199     return NS_ERROR_FAILURE;
01200   }
01201 
01202   result = mgr->Clear();
01203 
01204   if (NS_FAILED(result)) {
01205     printf("ERROR: Clear() failed. (%d)\n", result);
01206     return result;
01207   }
01208 
01209   printf("passed\n");
01210 
01211   /*******************************************************************
01212    *
01213    * Execute 20 transactions. Afterwards, we should have 10
01214    * transactions on the undo stack:
01215    *
01216    *******************************************************************/
01217 
01218   printf("Execute 20 transactions ... ");
01219 
01220   for (i = 1; i <= 20; i++) {
01221     tximpl = factory->create(mgr, NONE_FLAG);
01222 
01223     if (!tximpl) {
01224       printf("ERROR: Failed to allocate transaction %d.\n", i);
01225       return NS_ERROR_OUT_OF_MEMORY;
01226     }
01227 
01228     tx = 0;
01229     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
01230     if (NS_FAILED(result)) {
01231       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
01232              i, result);
01233       return result;
01234     }
01235 
01236     result = mgr->DoTransaction(tx);
01237     if (NS_FAILED(result)) {
01238       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
01239       return result;
01240     }
01241 
01242     tx->Release();
01243   }
01244 
01245   result = mgr->GetNumberOfUndoItems(&numitems);
01246 
01247   if (NS_FAILED(result)) {
01248     printf("ERROR: GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
01249            result);
01250     return result;
01251   }
01252 
01253   if (numitems != 10) {
01254     printf("ERROR: GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
01255            numitems, result);
01256     return NS_ERROR_FAILURE;
01257   }
01258 
01259   result = mgr->GetNumberOfRedoItems(&numitems);
01260 
01261   if (NS_FAILED(result)) {
01262     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
01263            result);
01264     return result;
01265   }
01266 
01267   if (numitems != 0) {
01268     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
01269            numitems, result);
01270     return NS_ERROR_FAILURE;
01271   }
01272 
01273   printf("passed\n");
01274 
01275   /*******************************************************************
01276    *
01277    * Execute 20 transient transactions. Afterwards, we should still
01278    * have the same 10 transactions on the undo stack:
01279    *
01280    *******************************************************************/
01281 
01282   printf("Execute 20 transient transactions ... ");
01283 
01284   u1 = u2 = r1 = r2 = 0;
01285 
01286   result = mgr->PeekUndoStack(&u1);
01287 
01288   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
01289 
01290   if (NS_FAILED(result)) {
01291     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
01292     return result;
01293   }
01294 
01295   result = mgr->PeekRedoStack(&r1);
01296 
01297   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
01298 
01299   if (NS_FAILED(result)) {
01300     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
01301     return result;
01302   }
01303 
01304   for (i = 1; i <= 20; i++) {
01305     tximpl = factory->create(mgr, TRANSIENT_FLAG);
01306 
01307     if (!tximpl) {
01308       printf("ERROR: Failed to allocate transaction %d.\n", i);
01309       return NS_ERROR_OUT_OF_MEMORY;
01310     }
01311 
01312     tx = 0;
01313     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
01314     if (NS_FAILED(result)) {
01315       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
01316              i, result);
01317       return result;
01318     }
01319 
01320     result = mgr->DoTransaction(tx);
01321     if (NS_FAILED(result)) {
01322       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
01323       return result;
01324     }
01325 
01326     tx->Release();
01327   }
01328 
01329   result = mgr->PeekUndoStack(&u2);
01330 
01331   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
01332 
01333   if (NS_FAILED(result)) {
01334     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
01335     return result;
01336   }
01337 
01338   if (u1 != u2) {
01339     printf("ERROR: Top of undo stack changed. (%d)\n", result);
01340     return NS_ERROR_FAILURE;
01341   }
01342 
01343   result = mgr->PeekRedoStack(&r2);
01344 
01345   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
01346 
01347   if (NS_FAILED(result)) {
01348     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
01349     return result;
01350   }
01351 
01352   if (r1 != r2) {
01353     printf("ERROR: Top of redo stack changed. (%d)\n", result);
01354     return NS_ERROR_FAILURE;
01355   }
01356 
01357   result = mgr->GetNumberOfUndoItems(&numitems);
01358 
01359   if (NS_FAILED(result)) {
01360     printf("ERROR: GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
01361            result);
01362     return result;
01363   }
01364 
01365   if (numitems != 10) {
01366     printf("ERROR: GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
01367            numitems, result);
01368     return NS_ERROR_FAILURE;
01369   }
01370 
01371   result = mgr->GetNumberOfRedoItems(&numitems);
01372 
01373   if (NS_FAILED(result)) {
01374     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
01375            result);
01376     return result;
01377   }
01378 
01379   if (numitems != 0) {
01380     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
01381            numitems, result);
01382     return NS_ERROR_FAILURE;
01383   }
01384 
01385   printf("passed\n");
01386 
01387   /*******************************************************************
01388    *
01389    * Undo 4 transactions. Afterwards, we should have 6 transactions
01390    * on the undo stack, and 4 on the redo stack:
01391    *
01392    *******************************************************************/
01393 
01394   printf("Undo 4 transactions ... ");
01395 
01396   for (i = 1; i <= 4; i++) {
01397     result = mgr->UndoTransaction();
01398     if (NS_FAILED(result)) {
01399       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
01400       return result;
01401     }
01402   }
01403 
01404   result = mgr->GetNumberOfUndoItems(&numitems);
01405 
01406   if (NS_FAILED(result)) {
01407     printf("ERROR: GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
01408            result);
01409     return result;
01410   }
01411 
01412   if (numitems != 6) {
01413     printf("ERROR: GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
01414            numitems, result);
01415     return NS_ERROR_FAILURE;
01416   }
01417 
01418   result = mgr->GetNumberOfRedoItems(&numitems);
01419 
01420   if (NS_FAILED(result)) {
01421     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
01422            result);
01423     return result;
01424   }
01425 
01426   if (numitems != 4) {
01427     printf("ERROR: GetNumberOfRedoItems() expected 4 got %d. (%d)\n",
01428            numitems, result);
01429     return NS_ERROR_FAILURE;
01430   }
01431 
01432   printf("passed\n");
01433 
01434   /*******************************************************************
01435    *
01436    * Redo 2 transactions. Afterwards, we should have 8 transactions
01437    * on the undo stack, and 2 on the redo stack:
01438    *
01439    *******************************************************************/
01440 
01441   printf("Redo 2 transactions ... ");
01442 
01443   for (i = 1; i <= 2; ++i) {
01444     result = mgr->RedoTransaction();
01445     if (NS_FAILED(result)) {
01446       printf("ERROR: Failed to redo transaction %d. (%d)\n", i, result);
01447       return result;
01448     }
01449   }
01450 
01451   result = mgr->GetNumberOfUndoItems(&numitems);
01452 
01453   if (NS_FAILED(result)) {
01454     printf("ERROR: GetNumberOfUndoItems() on undo stack with 8 items failed. (%d)\n",
01455            result);
01456     return result;
01457   }
01458 
01459   if (numitems != 8) {
01460     printf("ERROR: GetNumberOfUndoItems() expected 8 got %d. (%d)\n",
01461            numitems, result);
01462     return NS_ERROR_FAILURE;
01463   }
01464 
01465   result = mgr->GetNumberOfRedoItems(&numitems);
01466 
01467   if (NS_FAILED(result)) {
01468     printf("ERROR: GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
01469            result);
01470     return result;
01471   }
01472 
01473   if (numitems != 2) {
01474     printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
01475            numitems, result);
01476     return NS_ERROR_FAILURE;
01477   }
01478 
01479   printf("passed\n");
01480 
01481   /*******************************************************************
01482    *
01483    * Execute a new transaction. The redo stack should get pruned!
01484    *
01485    *******************************************************************/
01486 
01487   printf("Check if new transactions prune the redo stack ... ");
01488 
01489   tximpl = factory->create(mgr, NONE_FLAG);
01490 
01491   if (!tximpl) {
01492     printf("ERROR: Failed to allocate transaction.\n");
01493     return NS_ERROR_OUT_OF_MEMORY;
01494   }
01495 
01496   tx     = 0;
01497 
01498   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
01499 
01500   if (NS_FAILED(result)) {
01501     printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);
01502     return result;
01503   }
01504 
01505   result = mgr->DoTransaction(tx);
01506   if (NS_FAILED(result)) {
01507     printf("ERROR: Failed to execute transaction. (%d)\n", result);
01508     return result;
01509   }
01510 
01511   tx->Release();
01512 
01513   result = mgr->GetNumberOfUndoItems(&numitems);
01514 
01515   if (NS_FAILED(result)) {
01516     printf("ERROR: GetNumberOfUndoItems() on undo stack with 9 items failed. (%d)\n",
01517            result);
01518     return result;
01519   }
01520 
01521   if (numitems != 9) {
01522     printf("ERROR: GetNumberOfUndoItems() expected 9 got %d. (%d)\n",
01523            numitems, result);
01524     return NS_ERROR_FAILURE;
01525   }
01526 
01527   result = mgr->GetNumberOfRedoItems(&numitems);
01528 
01529   if (NS_FAILED(result)) {
01530     printf("ERROR: GetNumberOfRedoItems() on redo stack with 0 items failed. (%d)\n",
01531            result);
01532     return result;
01533   }
01534 
01535   if (numitems != 0) {
01536     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
01537            numitems, result);
01538     return NS_ERROR_FAILURE;
01539   }
01540 
01541   printf("passed\n");
01542 
01543   /*******************************************************************
01544    *
01545    * Undo 4 transactions then clear the undo and redo stacks.
01546    *
01547    *******************************************************************/
01548 
01549   printf("Undo 4 transactions then clear the undo and redo stacks ... ");
01550 
01551   for (i = 1; i <= 4; ++i) {
01552     result = mgr->UndoTransaction();
01553     if (NS_FAILED(result)) {
01554       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
01555       return result;
01556     }
01557   }
01558 
01559   result = mgr->GetNumberOfUndoItems(&numitems);
01560 
01561   if (NS_FAILED(result)) {
01562     printf("ERROR: GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
01563            result);
01564     return result;
01565   }
01566 
01567   if (numitems != 5) {
01568     printf("ERROR: GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
01569            numitems, result);
01570     return NS_ERROR_FAILURE;
01571   }
01572 
01573   result = mgr->GetNumberOfRedoItems(&numitems);
01574 
01575   if (NS_FAILED(result)) {
01576     printf("ERROR: GetNumberOfRedoItems() on redo stack with 4 items failed. (%d)\n",
01577            result);
01578     return result;
01579   }
01580 
01581   if (numitems != 4) {
01582     printf("ERROR: GetNumberOfRedoItems() expected 4 got %d. (%d)\n",
01583            numitems, result);
01584     return NS_ERROR_FAILURE;
01585   }
01586 
01587   result = mgr->Clear();
01588 
01589   if (NS_FAILED(result)) {
01590     printf("ERROR: Clear() failed. (%d)\n",
01591            result);
01592     return result;
01593   }
01594 
01595   result = mgr->GetNumberOfUndoItems(&numitems);
01596 
01597   if (NS_FAILED(result)) {
01598     printf("ERROR: GetNumberOfUndoItems() on cleared undo stack failed. (%d)\n",
01599            result);
01600     return result;
01601   }
01602 
01603   if (numitems != 0) {
01604     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
01605            numitems, result);
01606     return NS_ERROR_FAILURE;
01607   }
01608 
01609   result = mgr->GetNumberOfRedoItems(&numitems);
01610 
01611   if (NS_FAILED(result)) {
01612     printf("ERROR: GetNumberOfRedoItems() on empty cleared stack failed. (%d)\n",
01613            result);
01614     return result;
01615   }
01616 
01617   if (numitems != 0) {
01618     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
01619            numitems, result);
01620     return NS_ERROR_FAILURE;
01621   }
01622 
01623   printf("passed\n");
01624 
01625   /*******************************************************************
01626    *
01627    * Execute 5 transactions.
01628    *
01629    *******************************************************************/
01630 
01631   printf("Execute 5 transactions ... ");
01632 
01633   for (i = 1; i <= 5; i++) {
01634     tximpl = factory->create(mgr, NONE_FLAG);
01635 
01636     if (!tximpl) {
01637       printf("ERROR: Failed to allocate transaction %d.\n", i);
01638       return NS_ERROR_OUT_OF_MEMORY;
01639     }
01640 
01641     tx = 0;
01642     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
01643     if (NS_FAILED(result)) {
01644       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
01645              i, result);
01646       return result;
01647     }
01648 
01649     result = mgr->DoTransaction(tx);
01650     if (NS_FAILED(result)) {
01651       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
01652       return result;
01653     }
01654 
01655     tx->Release();
01656   }
01657 
01658   result = mgr->GetNumberOfUndoItems(&numitems);
01659 
01660   if (NS_FAILED(result)) {
01661     printf("ERROR: GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
01662            result);
01663     return result;
01664   }
01665 
01666   if (numitems != 5) {
01667     printf("ERROR: GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
01668            numitems, result);
01669     return NS_ERROR_FAILURE;
01670   }
01671 
01672   result = mgr->GetNumberOfRedoItems(&numitems);
01673 
01674   if (NS_FAILED(result)) {
01675     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
01676            result);
01677     return result;
01678   }
01679 
01680   if (numitems != 0) {
01681     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
01682            numitems, result);
01683     return NS_ERROR_FAILURE;
01684   }
01685 
01686   printf("passed\n");
01687 
01688   /*******************************************************************
01689    *
01690    * Test transaction DoTransaction() error:
01691    *
01692    *******************************************************************/
01693 
01694   printf("Test transaction DoTransaction() error ... ");
01695 
01696   tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
01697 
01698   if (!tximpl) {
01699     printf("ERROR: Failed to allocate transaction.\n");
01700     return NS_ERROR_OUT_OF_MEMORY;
01701   }
01702 
01703   tx     = 0;
01704 
01705   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
01706 
01707   if (NS_FAILED(result)) {
01708     printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);
01709     return result;
01710   }
01711 
01712   u1 = u2 = r1 = r2 = 0;
01713 
01714   result = mgr->PeekUndoStack(&u1);
01715 
01716   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
01717 
01718   if (NS_FAILED(result)) {
01719     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
01720     return result;
01721   }
01722 
01723   result = mgr->PeekRedoStack(&r1);
01724 
01725   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
01726 
01727   if (NS_FAILED(result)) {
01728     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
01729     return result;
01730   }
01731 
01732   result = mgr->DoTransaction(tx);
01733 
01734   if (NS_FAILED(result) && result != NS_ERROR_FAILURE) {
01735     printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);
01736     return result;
01737   }
01738 
01739   tx->Release();
01740 
01741   result = mgr->PeekUndoStack(&u2);
01742 
01743   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
01744 
01745   if (NS_FAILED(result)) {
01746     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
01747     return result;
01748   }
01749 
01750   if (u1 != u2) {
01751     printf("ERROR: Top of undo stack changed. (%d)\n", result);
01752     return NS_ERROR_FAILURE;
01753   }
01754 
01755   result = mgr->PeekRedoStack(&r2);
01756 
01757   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
01758 
01759   if (NS_FAILED(result)) {
01760     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
01761     return result;
01762   }
01763 
01764   if (r1 != r2) {
01765     printf("ERROR: Top of redo stack changed. (%d)\n", result);
01766     return NS_ERROR_FAILURE;
01767   }
01768 
01769   result = mgr->GetNumberOfUndoItems(&numitems);
01770 
01771   if (NS_FAILED(result)) {
01772     printf("ERROR: GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
01773            result);
01774     return result;
01775   }
01776 
01777   if (numitems != 5) {
01778     printf("ERROR: GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
01779            numitems, result);
01780     return NS_ERROR_FAILURE;
01781   }
01782 
01783   result = mgr->GetNumberOfRedoItems(&numitems);
01784 
01785   if (NS_FAILED(result)) {
01786     printf("ERROR: GetNumberOfRedoItems() on empty redo stack. (%d)\n",
01787            result);
01788     return result;
01789   }
01790 
01791   if (numitems != 0) {
01792     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
01793            numitems, result);
01794     return NS_ERROR_FAILURE;
01795   }
01796 
01797   printf("passed\n");
01798 
01799   /*******************************************************************
01800    *
01801    * Test transaction UndoTransaction() error:
01802    *
01803    *******************************************************************/
01804 
01805   printf("Test transaction UndoTransaction() error ... ");
01806 
01807   tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
01808 
01809   if (!tximpl) {
01810     printf("ERROR: Failed to allocate transaction.\n");
01811     return NS_ERROR_OUT_OF_MEMORY;
01812   }
01813 
01814   tx     = 0;
01815 
01816   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
01817 
01818   if (NS_FAILED(result)) {
01819     printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);
01820     return result;
01821   }
01822 
01823   result = mgr->DoTransaction(tx);
01824 
01825   if (NS_FAILED(result)) {
01826     printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);
01827     return result;
01828   }
01829 
01830   tx->Release();
01831 
01832   u1 = u2 = r1 = r2 = 0;
01833 
01834   result = mgr->PeekUndoStack(&u1);
01835 
01836   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
01837 
01838   if (NS_FAILED(result)) {
01839     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
01840     return result;
01841   }
01842 
01843   result = mgr->PeekRedoStack(&r1);
01844 
01845   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
01846 
01847   if (NS_FAILED(result)) {
01848     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
01849     return result;
01850   }
01851 
01852   result = mgr->UndoTransaction();
01853 
01854   if (NS_FAILED(result) && result != NS_ERROR_FAILURE) {
01855     printf("ERROR: UndoTransaction() returned unexpected error. (%d)\n", result);
01856     return result;
01857   }
01858 
01859   result = mgr->PeekUndoStack(&u2);
01860 
01861   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
01862 
01863   if (NS_FAILED(result)) {
01864     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
01865     return result;
01866   }
01867 
01868   if (u1 != u2) {
01869     printf("ERROR: Top of undo stack changed. (%d)\n", result);
01870     return NS_ERROR_FAILURE;
01871   }
01872 
01873   result = mgr->PeekRedoStack(&r2);
01874 
01875   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
01876 
01877   if (NS_FAILED(result)) {
01878     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
01879     return result;
01880   }
01881 
01882   if (r1 != r2) {
01883     printf("ERROR: Top of redo stack changed. (%d)\n", result);
01884     return NS_ERROR_FAILURE;
01885   }
01886 
01887   result = mgr->GetNumberOfUndoItems(&numitems);
01888 
01889   if (NS_FAILED(result)) {
01890     printf("ERROR: GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
01891            result);
01892     return result;
01893   }
01894 
01895   if (numitems != 6) {
01896     printf("ERROR: GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
01897            numitems, result);
01898     return NS_ERROR_FAILURE;
01899   }
01900 
01901   result = mgr->GetNumberOfRedoItems(&numitems);
01902 
01903   if (NS_FAILED(result)) {
01904     printf("ERROR: GetNumberOfRedoItems() on empty redo stack. (%d)\n",
01905            result);
01906     return result;
01907   }
01908 
01909   if (numitems != 0) {
01910     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
01911            numitems, result);
01912     return NS_ERROR_FAILURE;
01913   }
01914 
01915   printf("passed\n");
01916 
01917   /*******************************************************************
01918    *
01919    * Test transaction RedoTransaction() error:
01920    *
01921    *******************************************************************/
01922 
01923   printf("Test transaction RedoTransaction() error ... ");
01924 
01925   tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
01926 
01927   if (!tximpl) {
01928     printf("ERROR: Failed to allocate transaction.\n");
01929     return NS_ERROR_OUT_OF_MEMORY;
01930   }
01931 
01932   tx     = 0;
01933 
01934   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
01935 
01936   if (NS_FAILED(result)) {
01937     printf("ERROR: QueryInterface() failed for RedoErrorTransaction. (%d)\n",
01938            result);
01939     return result;
01940   }
01941 
01942   result = mgr->DoTransaction(tx);
01943 
01944   if (NS_FAILED(result)) {
01945     printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);
01946     return result;
01947   }
01948 
01949   tx->Release();
01950 
01951   //
01952   // Execute a normal transaction to be used in a later test:
01953   //
01954 
01955   tximpl = factory->create(mgr, NONE_FLAG);
01956 
01957   if (!tximpl) {
01958     printf("ERROR: Failed to allocate transaction.\n");
01959     return NS_ERROR_OUT_OF_MEMORY;
01960   }
01961 
01962   tx     = 0;
01963 
01964   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
01965 
01966   if (NS_FAILED(result)) {
01967     printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);
01968     return result;
01969   }
01970 
01971   result = mgr->DoTransaction(tx);
01972 
01973   if (NS_FAILED(result)) {
01974     printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);
01975     return result;
01976   }
01977 
01978   tx->Release();
01979 
01980   //
01981   // Undo the 2 transactions just executed.
01982   //
01983 
01984   for (i = 1; i <= 2; ++i) {
01985     result = mgr->UndoTransaction();
01986     if (NS_FAILED(result)) {
01987       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
01988       return result;
01989     }
01990   }
01991 
01992   //
01993   // The RedoErrorTransaction should now be at the top of the redo stack!
01994   //
01995 
01996   u1 = u2 = r1 = r2 = 0;
01997 
01998   result = mgr->PeekUndoStack(&u1);
01999 
02000   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
02001 
02002   if (NS_FAILED(result)) {
02003     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
02004     return result;
02005   }
02006 
02007   result = mgr->PeekRedoStack(&r1);
02008 
02009   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
02010 
02011   if (NS_FAILED(result)) {
02012     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
02013     return result;
02014   }
02015 
02016   result = mgr->RedoTransaction();
02017 
02018   if (NS_FAILED(result) && result != NS_ERROR_FAILURE) {
02019     printf("ERROR: RedoTransaction() returned unexpected error. (%d)\n", result);
02020     return result;
02021   }
02022 
02023   result = mgr->PeekUndoStack(&u2);
02024 
02025   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
02026 
02027   if (NS_FAILED(result)) {
02028     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
02029     return result;
02030   }
02031 
02032   if (u1 != u2) {
02033     printf("ERROR: Top of undo stack changed. (%d)\n", result);
02034     return NS_ERROR_FAILURE;
02035   }
02036 
02037   result = mgr->PeekRedoStack(&r2);
02038 
02039   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
02040 
02041   if (NS_FAILED(result)) {
02042     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
02043     return result;
02044   }
02045 
02046   if (r1 != r2) {
02047     printf("ERROR: Top of redo stack changed. (%d)\n", result);
02048     return NS_ERROR_FAILURE;
02049   }
02050 
02051   result = mgr->GetNumberOfUndoItems(&numitems);
02052 
02053   if (NS_FAILED(result)) {
02054     printf("ERROR: GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
02055            result);
02056     return result;
02057   }
02058 
02059   if (numitems != 6) {
02060     printf("ERROR: GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
02061            numitems, result);
02062     return NS_ERROR_FAILURE;
02063   }
02064 
02065   result = mgr->GetNumberOfRedoItems(&numitems);
02066 
02067   if (NS_FAILED(result)) {
02068     printf("ERROR: GetNumberOfRedoItems() on empty redo stack. (%d)\n",
02069            result);
02070     return result;
02071   }
02072 
02073   if (numitems != 2) {
02074     printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
02075            numitems, result);
02076     return NS_ERROR_FAILURE;
02077   }
02078 
02079   printf("passed\n");
02080 
02081   /*******************************************************************
02082    *
02083    * Make sure that setting the transaction manager's max transaction
02084    * count to zero, clears both the undo and redo stacks, and executes
02085    * all new commands without pushing them on the undo stack!
02086    *
02087    *******************************************************************/
02088 
02089   printf("Test max transaction count of zero ... ");
02090 
02091   result = mgr->SetMaxTransactionCount(0);
02092 
02093   if (NS_FAILED(result)) {
02094     printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);
02095     return result;
02096   }
02097 
02098   result = mgr->GetNumberOfUndoItems(&numitems);
02099 
02100   if (NS_FAILED(result)) {
02101     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
02102            result);
02103     return result;
02104   }
02105 
02106   if (numitems != 0) {
02107     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
02108            numitems, result);
02109     return NS_ERROR_FAILURE;
02110   }
02111 
02112   result = mgr->GetNumberOfRedoItems(&numitems);
02113 
02114   if (NS_FAILED(result)) {
02115     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
02116            result);
02117     return result;
02118   }
02119 
02120   if (numitems != 0) {
02121     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
02122            numitems, result);
02123     return NS_ERROR_FAILURE;
02124   }
02125 
02126   for (i = 1; i <= 20; i++) {
02127     tximpl = factory->create(mgr, NONE_FLAG);
02128 
02129     if (!tximpl) {
02130       printf("ERROR: Failed to allocate transaction %d.\n", i);
02131       return NS_ERROR_OUT_OF_MEMORY;
02132     }
02133 
02134     tx = 0;
02135     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
02136     if (NS_FAILED(result)) {
02137       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
02138              i, result);
02139       return result;
02140     }
02141 
02142     result = mgr->DoTransaction(tx);
02143     if (NS_FAILED(result)) {
02144       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
02145       return result;
02146     }
02147 
02148     tx->Release();
02149 
02150     result = mgr->GetNumberOfUndoItems(&numitems);
02151 
02152     if (NS_FAILED(result)) {
02153       printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
02154              result);
02155       return result;
02156     }
02157 
02158     if (numitems != 0) {
02159       printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
02160              numitems, result);
02161       return NS_ERROR_FAILURE;
02162     }
02163 
02164     result = mgr->GetNumberOfRedoItems(&numitems);
02165 
02166     if (NS_FAILED(result)) {
02167       printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
02168              result);
02169       return result;
02170     }
02171 
02172     if (numitems != 0) {
02173       printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
02174              numitems, result);
02175       return NS_ERROR_FAILURE;
02176     }
02177   }
02178 
02179   printf("passed\n");
02180 
02181   /*******************************************************************
02182    *
02183    * Make sure that setting the transaction manager's max transaction
02184    * count to something greater than the number of transactions on
02185    * both the undo and redo stacks causes no pruning of the stacks:
02186    *
02187    *******************************************************************/
02188 
02189   printf("Test SetMaxTransactionCount() greater than num stack items ... ");
02190 
02191   result = mgr->SetMaxTransactionCount(-1);
02192 
02193   if (NS_FAILED(result)) {
02194     printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);
02195     return result;
02196   }
02197 
02198   // Push 20 transactions on the undo stack:
02199 
02200   for (i = 1; i <= 20; i++) {
02201     tximpl = factory->create(mgr, NONE_FLAG);
02202 
02203     if (!tximpl) {
02204       printf("ERROR: Failed to allocate transaction %d.\n", i);
02205       return NS_ERROR_OUT_OF_MEMORY;
02206     }
02207 
02208     tx = 0;
02209     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
02210     if (NS_FAILED(result)) {
02211       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
02212              i, result);
02213       return result;
02214     }
02215 
02216     result = mgr->DoTransaction(tx);
02217     if (NS_FAILED(result)) {
02218       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
02219       return result;
02220     }
02221 
02222     tx->Release();
02223 
02224     result = mgr->GetNumberOfUndoItems(&numitems);
02225 
02226     if (NS_FAILED(result)) {
02227       printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
02228              result);
02229       return result;
02230     }
02231 
02232     if (numitems != i) {
02233       printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
02234              numitems, result);
02235       return NS_ERROR_FAILURE;
02236     }
02237 
02238     result = mgr->GetNumberOfRedoItems(&numitems);
02239 
02240     if (NS_FAILED(result)) {
02241       printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
02242              result);
02243       return result;
02244     }
02245 
02246     if (numitems != 0) {
02247       printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
02248              numitems, result);
02249       return NS_ERROR_FAILURE;
02250     }
02251   }
02252 
02253   for (i = 1; i <= 10; i++) {
02254 
02255     result = mgr->UndoTransaction();
02256     if (NS_FAILED(result)) {
02257       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
02258       return result;
02259     }
02260   }
02261   result = mgr->GetNumberOfUndoItems(&numitems);
02262 
02263   if (NS_FAILED(result)) {
02264     printf("ERROR: GetNumberOfUndoItems() on empty undo stack with 10 items failed. (%d)\n",
02265            result);
02266     return result;
02267   }
02268 
02269   if (numitems != 10) {
02270     printf("ERROR: GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
02271            numitems, result);
02272     return NS_ERROR_FAILURE;
02273   }
02274 
02275   result = mgr->GetNumberOfRedoItems(&numitems);
02276 
02277   if (NS_FAILED(result)) {
02278     printf("ERROR: GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
02279            result);
02280     return result;
02281   }
02282 
02283   if (numitems != 10) {
02284     printf("ERROR: GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
02285            numitems, result);
02286     return NS_ERROR_FAILURE;
02287   }
02288 
02289   u1 = u2 = r1 = r2 = 0;
02290 
02291   result = mgr->PeekUndoStack(&u1);
02292 
02293   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
02294 
02295   if (NS_FAILED(result)) {
02296     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
02297     return result;
02298   }
02299 
02300   result = mgr->PeekRedoStack(&r1);
02301 
02302   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
02303 
02304   if (NS_FAILED(result)) {
02305     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
02306     return result;
02307   }
02308 
02309   result = mgr->SetMaxTransactionCount(25);
02310 
02311   if (NS_FAILED(result)) {
02312     printf("ERROR: SetMaxTransactionCount(25) failed. (%d)\n", result);
02313     return result;
02314   }
02315 
02316   result = mgr->PeekUndoStack(&u2);
02317 
02318   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
02319 
02320   if (NS_FAILED(result)) {
02321     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
02322     return result;
02323   }
02324 
02325   if (u1 != u2) {
02326     printf("ERROR: Top of undo stack changed. (%d)\n", result);
02327     return NS_ERROR_FAILURE;
02328   }
02329 
02330   result = mgr->PeekRedoStack(&r2);
02331 
02332   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
02333 
02334   if (NS_FAILED(result)) {
02335     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
02336     return result;
02337   }
02338 
02339   if (r1 != r2) {
02340     printf("ERROR: Top of redo stack changed. (%d)\n", result);
02341     return NS_ERROR_FAILURE;
02342   }
02343 
02344   result = mgr->GetNumberOfUndoItems(&numitems);
02345 
02346   if (NS_FAILED(result)) {
02347     printf("ERROR: GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
02348            result);
02349     return result;
02350   }
02351 
02352   if (numitems != 10) {
02353     printf("ERROR: GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
02354            numitems, result);
02355     return NS_ERROR_FAILURE;
02356   }
02357 
02358   result = mgr->GetNumberOfRedoItems(&numitems);
02359 
02360   if (NS_FAILED(result)) {
02361     printf("ERROR: GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
02362            result);
02363     return result;
02364   }
02365 
02366   if (numitems != 10) {
02367     printf("ERROR: GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
02368            numitems, result);
02369     return NS_ERROR_FAILURE;
02370   }
02371 
02372   printf("passed\n");
02373 
02374   /*******************************************************************
02375    *
02376    * Test undo stack pruning by setting the transaction
02377    * manager's max transaction count to a number lower than the
02378    * number of transactions on both the undo and redo stacks:
02379    *
02380    *******************************************************************/
02381 
02382   printf("Test SetMaxTransactionCount() pruning undo stack ... ");
02383 
02384   u1 = u2 = r1 = r2 = 0;
02385 
02386   result = mgr->PeekUndoStack(&u1);
02387 
02388   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
02389 
02390   if (NS_FAILED(result)) {
02391     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
02392     return result;
02393   }
02394 
02395   result = mgr->PeekRedoStack(&r1);
02396 
02397   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
02398 
02399   if (NS_FAILED(result)) {
02400     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
02401     return result;
02402   }
02403 
02404   result = mgr->SetMaxTransactionCount(15);
02405 
02406   if (NS_FAILED(result)) {
02407     printf("ERROR: SetMaxTransactionCount(25) failed. (%d)\n", result);
02408     return result;
02409   }
02410 
02411   result = mgr->PeekUndoStack(&u2);
02412 
02413   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
02414 
02415   if (NS_FAILED(result)) {
02416     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
02417     return result;
02418   }
02419 
02420   if (u1 != u2) {
02421     printf("ERROR: Top of undo stack changed. (%d)\n", result);
02422     return NS_ERROR_FAILURE;
02423   }
02424 
02425   result = mgr->PeekRedoStack(&r2);
02426 
02427   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
02428 
02429   if (NS_FAILED(result)) {
02430     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
02431     return result;
02432   }
02433 
02434   if (r1 != r2) {
02435     printf("ERROR: Top of redo stack changed. (%d)\n", result);
02436     return NS_ERROR_FAILURE;
02437   }
02438 
02439   result = mgr->GetNumberOfUndoItems(&numitems);
02440 
02441   if (NS_FAILED(result)) {
02442     printf("ERROR: GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
02443            result);
02444     return result;
02445   }
02446 
02447   if (numitems != 5) {
02448     printf("ERROR: GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
02449            numitems, result);
02450     return NS_ERROR_FAILURE;
02451   }
02452 
02453   result = mgr->GetNumberOfRedoItems(&numitems);
02454 
02455   if (NS_FAILED(result)) {
02456     printf("ERROR: GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
02457            result);
02458     return result;
02459   }
02460 
02461   if (numitems != 10) {
02462     printf("ERROR: GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
02463            numitems, result);
02464     return NS_ERROR_FAILURE;
02465   }
02466 
02467   printf("passed\n");
02468 
02469   /*******************************************************************
02470    *
02471    * Test redo stack pruning by setting the transaction
02472    * manager's max transaction count to a number lower than the
02473    * number of transactions on both the undo and redo stacks:
02474    *
02475    *******************************************************************/
02476 
02477   printf("Test SetMaxTransactionCount() pruning redo stack ... ");
02478 
02479   u1 = u2 = r1 = r2 = 0;
02480 
02481   result = mgr->PeekUndoStack(&u1);
02482 
02483   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
02484 
02485   if (NS_FAILED(result)) {
02486     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
02487     return result;
02488   }
02489 
02490   result = mgr->PeekRedoStack(&r1);
02491 
02492   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
02493 
02494   if (NS_FAILED(result)) {
02495     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
02496     return result;
02497   }
02498 
02499   result = mgr->SetMaxTransactionCount(5);
02500 
02501   if (NS_FAILED(result)) {
02502     printf("ERROR: SetMaxTransactionCount(25) failed. (%d)\n", result);
02503     return result;
02504   }
02505 
02506   result = mgr->PeekUndoStack(&u2);
02507 
02508   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
02509 
02510   if (NS_FAILED(result)) {
02511     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
02512     return result;
02513   }
02514 
02515   if (u1 == u2 || u2) {
02516     printf("ERROR: Unexpected item at top of undo stack. (%d)\n", result);
02517     return NS_ERROR_FAILURE;
02518   }
02519 
02520   result = mgr->PeekRedoStack(&r2);
02521 
02522   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
02523 
02524   if (NS_FAILED(result)) {
02525     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
02526     return result;
02527   }
02528 
02529   if (r1 != r2) {
02530     printf("ERROR: Top of redo stack changed. (%d)\n", result);
02531     return NS_ERROR_FAILURE;
02532   }
02533 
02534   result = mgr->GetNumberOfUndoItems(&numitems);
02535 
02536   if (NS_FAILED(result)) {
02537     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
02538            result);
02539     return result;
02540   }
02541 
02542   if (numitems != 0) {
02543     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
02544            numitems, result);
02545     return NS_ERROR_FAILURE;
02546   }
02547 
02548   result = mgr->GetNumberOfRedoItems(&numitems);
02549 
02550   if (NS_FAILED(result)) {
02551     printf("ERROR: GetNumberOfRedoItems() on redo stack with 5 items failed. (%d)\n",
02552            result);
02553     return result;
02554   }
02555 
02556   if (numitems != 5) {
02557     printf("ERROR: GetNumberOfRedoItems() expected 5 got %d. (%d)\n",
02558            numitems, result);
02559     return NS_ERROR_FAILURE;
02560   }
02561 
02562   printf("passed\n");
02563 
02564   /*******************************************************************
02565    *
02566    * Release the transaction manager. Any transactions on the undo
02567    * and redo stack should automatically be released:
02568    *
02569    *******************************************************************/
02570 
02571   printf("Release the transaction manager ... ");
02572 
02573   result = mgr->SetMaxTransactionCount(-1);
02574 
02575   if (NS_FAILED(result)) {
02576     printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);
02577     return result;
02578   }
02579 
02580   // Push 20 transactions on the undo stack:
02581 
02582   for (i = 1; i <= 20; i++) {
02583     tximpl = factory->create(mgr, NONE_FLAG);
02584 
02585     if (!tximpl) {
02586       printf("ERROR: Failed to allocate transaction %d.\n", i);
02587       return NS_ERROR_OUT_OF_MEMORY;
02588     }
02589 
02590     tx = 0;
02591     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
02592     if (NS_FAILED(result)) {
02593       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
02594              i, result);
02595       return result;
02596     }
02597 
02598     result = mgr->DoTransaction(tx);
02599     if (NS_FAILED(result)) {
02600       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
02601       return result;
02602     }
02603 
02604     tx->Release();
02605 
02606     result = mgr->GetNumberOfUndoItems(&numitems);
02607 
02608     if (NS_FAILED(result)) {
02609       printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
02610              result);
02611       return result;
02612     }
02613 
02614     if (numitems != i) {
02615       printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
02616              numitems, result);
02617       return NS_ERROR_FAILURE;
02618     }
02619 
02620     result = mgr->GetNumberOfRedoItems(&numitems);
02621 
02622     if (NS_FAILED(result)) {
02623       printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
02624              result);
02625       return result;
02626     }
02627 
02628     if (numitems != 0) {
02629       printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
02630              numitems, result);
02631       return NS_ERROR_FAILURE;
02632     }
02633   }
02634 
02635   for (i = 1; i <= 10; i++) {
02636 
02637     result = mgr->UndoTransaction();
02638     if (NS_FAILED(result)) {
02639       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
02640       return result;
02641     }
02642   }
02643   result = mgr->GetNumberOfUndoItems(&numitems);
02644 
02645   if (NS_FAILED(result)) {
02646     printf("ERROR: GetNumberOfUndoItems() on empty undo stack with 10 items failed. (%d)\n",
02647            result);
02648     return result;
02649   }
02650 
02651   if (numitems != 10) {
02652     printf("ERROR: GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
02653            numitems, result);
02654     return NS_ERROR_FAILURE;
02655   }
02656 
02657   result = mgr->GetNumberOfRedoItems(&numitems);
02658 
02659   if (NS_FAILED(result)) {
02660     printf("ERROR: GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
02661            result);
02662     return result;
02663   }
02664 
02665   if (numitems != 10) {
02666     printf("ERROR: GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
02667            numitems, result);
02668     return NS_ERROR_FAILURE;
02669   }
02670 
02671   printf("passed\n");
02672 
02673   /*******************************************************************
02674    *
02675    * Make sure number of transactions created matches number of
02676    * transactions destroyed!
02677    *
02678    *******************************************************************/
02679 
02680   printf("Number of transactions created and destroyed match ... ");
02681 
02682   if (sConstructorCount != sDestructorCount) {
02683     printf("ERROR: Transaction constructor count (%d) != destructor count (%d).\n",
02684            sConstructorCount, sDestructorCount);
02685     return NS_ERROR_FAILURE;
02686   }
02687 
02688   if (NS_FAILED(result)) {
02689     printf("ERROR: nsITransactionManager Release() failed. (%d)\n", result);
02690     return result;
02691   }
02692 
02693   printf("passed\n");
02694   printf("%d transactions processed during quick test.\n", sConstructorCount);
02695 
02696   return NS_OK;
02697 }
02698 
02699 nsresult
02700 simple_test()
02701 {
02702   /*******************************************************************
02703    *
02704    * Initialize globals for test.
02705    *
02706    *******************************************************************/
02707   reset_globals();
02708   sDestructorOrderArr = sSimpleTestDestructorOrderArr;
02709   sDoOrderArr         = sSimpleTestDoOrderArr;
02710   sUndoOrderArr       = sSimpleTestUndoOrderArr;
02711   sRedoOrderArr       = sSimpleTestRedoOrderArr;
02712 
02713   /*******************************************************************
02714    *
02715    * Run the quick test.
02716    *
02717    *******************************************************************/
02718 
02719   SimpleTransactionFactory factory;
02720 
02721   printf("\n-----------------------------------------------------\n");
02722   printf("- Begin Simple Transaction Test:\n");
02723   printf("-----------------------------------------------------\n");
02724 
02725   return quick_test(&factory);
02726 }
02727 
02728 nsresult
02729 aggregation_test()
02730 {
02731   /*******************************************************************
02732    *
02733    * Initialize globals for test.
02734    *
02735    *******************************************************************/
02736 
02737   reset_globals();
02738   sDestructorOrderArr = sAggregateTestDestructorOrderArr;
02739   sDoOrderArr         = sAggregateTestDoOrderArr;
02740   sUndoOrderArr       = sAggregateTestUndoOrderArr;
02741   sRedoOrderArr       = sAggregateTestRedoOrderArr;
02742 
02743   /*******************************************************************
02744    *
02745    * Run the quick test.
02746    *
02747    *******************************************************************/
02748 
02749   AggregateTransactionFactory factory(3,2);
02750 
02751   printf("\n-----------------------------------------------------\n");
02752   printf("- Begin Aggregate Transaction Test:\n");
02753   printf("-----------------------------------------------------\n");
02754 
02755   return quick_test(&factory);
02756 }
02757 
02758 nsresult
02759 quick_batch_test(TestTransactionFactory *factory)
02760 {
02761   /*******************************************************************
02762    *
02763    * Create a transaction manager implementation:
02764    *
02765    *******************************************************************/
02766 
02767   printf("Create transaction manager instance ... ");
02768 
02769   PRInt32 i, numitems = 0;
02770   nsCOMPtr<nsITransactionManager> mgr;
02771   nsITransaction *tx          = 0;
02772   TestTransaction *tximpl   = 0;
02773   nsITransaction *u1 = 0, *u2 = 0;
02774   nsITransaction *r1 = 0, *r2 = 0;
02775   nsresult result;
02776 
02777   mgr = do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
02778   if (NS_FAILED(result) || !mgr) {
02779     printf("ERROR: Failed to create Transaction Manager instance.\n");
02780     return NS_ERROR_OUT_OF_MEMORY;
02781   }
02782 
02783   printf("passed\n");
02784 
02785   /*******************************************************************
02786    *
02787    * Make sure an unbalanced call to EndBatch() with empty undo stack
02788    * throws an error!
02789    *
02790    *******************************************************************/
02791 
02792   printf("Test unbalanced EndBatch() with empty undo stack ... ");
02793 
02794   result = mgr->GetNumberOfUndoItems(&numitems);
02795 
02796   if (NS_FAILED(result)) {
02797     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
02798            result);
02799     return result;
02800   }
02801 
02802   if (numitems != 0) {
02803     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
02804            numitems, result);
02805     return NS_ERROR_FAILURE;
02806   }
02807 
02808   result = mgr->EndBatch();
02809 
02810   if (result != NS_ERROR_FAILURE) {
02811     printf("ERROR: EndBatch() returned unexpected status. (%d)\n", result);
02812     return result;
02813   }
02814 
02815   result = mgr->GetNumberOfUndoItems(&numitems);
02816 
02817   if (NS_FAILED(result)) {
02818     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
02819            result);
02820     return result;
02821   }
02822 
02823   if (numitems != 0) {
02824     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
02825            numitems, result);
02826     return NS_ERROR_FAILURE;
02827   }
02828 
02829   printf("passed\n");
02830 
02831 
02832   /*******************************************************************
02833    *
02834    * Make sure that an empty batch is not added to the undo stack
02835    * when it is closed.
02836    *
02837    *******************************************************************/
02838 
02839   printf("Test empty batch ... ");
02840 
02841   result = mgr->GetNumberOfUndoItems(&numitems);
02842 
02843   if (NS_FAILED(result)) {
02844     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
02845            result);
02846     return result;
02847   }
02848 
02849   if (numitems != 0) {
02850     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
02851            numitems, result);
02852     return NS_ERROR_FAILURE;
02853   }
02854 
02855   result = mgr->BeginBatch();
02856 
02857   if (NS_FAILED(result)) {
02858     printf("ERROR: BeginBatch() failed. (%d)\n", result);
02859     return result;
02860   }
02861 
02862   result = mgr->GetNumberOfUndoItems(&numitems);
02863 
02864   if (NS_FAILED(result)) {
02865     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
02866            result);
02867     return result;
02868   }
02869 
02870   if (numitems != 0) {
02871     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
02872            numitems, result);
02873     return NS_ERROR_FAILURE;
02874   }
02875 
02876   result = mgr->EndBatch();
02877 
02878   if (NS_FAILED(result)) {
02879     printf("ERROR: EndBatch() failed. (%d)\n", result);
02880     return result;
02881   }
02882 
02883   result = mgr->GetNumberOfUndoItems(&numitems);
02884 
02885   if (NS_FAILED(result)) {
02886     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
02887            result);
02888     return result;
02889   }
02890 
02891   if (numitems != 0) {
02892     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
02893            numitems, result);
02894     return NS_ERROR_FAILURE;
02895   }
02896 
02897   printf("passed\n");
02898 
02899   /*******************************************************************
02900    *
02901    * Execute 20 transactions. Afterwards, we should have 1
02902    * transaction on the undo stack:
02903    *
02904    *******************************************************************/
02905 
02906   printf("Execute 20 batched transactions ... ");
02907 
02908   result = mgr->BeginBatch();
02909 
02910   if (NS_FAILED(result)) {
02911     printf("ERROR: BeginBatch() failed. (%d)\n", result);
02912     return result;
02913   }
02914 
02915   for (i = 1; i <= 20; i++) {
02916     tximpl = factory->create(mgr, NONE_FLAG);
02917 
02918     if (!tximpl) {
02919       printf("ERROR: Failed to allocate transaction %d.\n", i);
02920       return NS_ERROR_OUT_OF_MEMORY;
02921     }
02922 
02923     tx = 0;
02924     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
02925     if (NS_FAILED(result)) {
02926       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
02927              i, result);
02928       return result;
02929     }
02930 
02931     result = mgr->DoTransaction(tx);
02932     if (NS_FAILED(result)) {
02933       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
02934       return result;
02935     }
02936 
02937     tx->Release();
02938   }
02939 
02940   result = mgr->GetNumberOfUndoItems(&numitems);
02941 
02942   if (NS_FAILED(result)) {
02943     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
02944            result);
02945     return result;
02946   }
02947 
02948   if (numitems != 0) {
02949     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
02950            numitems, result);
02951     return NS_ERROR_FAILURE;
02952   }
02953 
02954   result = mgr->EndBatch();
02955 
02956   if (NS_FAILED(result)) {
02957     printf("ERROR: EndBatch() failed. (%d)\n", result);
02958     return result;
02959   }
02960 
02961   result = mgr->GetNumberOfUndoItems(&numitems);
02962 
02963   if (NS_FAILED(result)) {
02964     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
02965            result);
02966     return result;
02967   }
02968 
02969   if (numitems != 1) {
02970     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
02971            numitems, result);
02972     return NS_ERROR_FAILURE;
02973   }
02974 
02975   printf("passed\n");
02976 
02977   /*******************************************************************
02978    *
02979    * Execute 20 transient transactions. Afterwards, we should still
02980    * have the same transaction on the undo stack:
02981    *
02982    *******************************************************************/
02983 
02984   printf("Execute 20 batched transient transactions ... ");
02985 
02986   u1 = u2 = r1 = r2 = 0;
02987 
02988   result = mgr->PeekUndoStack(&u1);
02989 
02990   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
02991 
02992   if (NS_FAILED(result)) {
02993     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
02994     return result;
02995   }
02996 
02997   result = mgr->PeekRedoStack(&r1);
02998 
02999   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
03000 
03001   if (NS_FAILED(result)) {
03002     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
03003     return result;
03004   }
03005 
03006   result = mgr->BeginBatch();
03007 
03008   if (NS_FAILED(result)) {
03009     printf("ERROR: BeginBatch() failed. (%d)\n", result);
03010     return result;
03011   }
03012 
03013   for (i = 1; i <= 20; i++) {
03014     tximpl = factory->create(mgr, TRANSIENT_FLAG);
03015 
03016     if (!tximpl) {
03017       printf("ERROR: Failed to allocate transaction %d.\n", i);
03018       return NS_ERROR_OUT_OF_MEMORY;
03019     }
03020 
03021     tx = 0;
03022     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
03023     if (NS_FAILED(result)) {
03024       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
03025              i, result);
03026       return result;
03027     }
03028 
03029     result = mgr->DoTransaction(tx);
03030     if (NS_FAILED(result)) {
03031       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
03032       return result;
03033     }
03034 
03035     tx->Release();
03036   }
03037 
03038   result = mgr->EndBatch();
03039 
03040   if (NS_FAILED(result)) {
03041     printf("ERROR: EndBatch() failed. (%d)\n", result);
03042     return result;
03043   }
03044 
03045   result = mgr->PeekUndoStack(&u2);
03046 
03047   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
03048 
03049   if (NS_FAILED(result)) {
03050     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
03051     return result;
03052   }
03053 
03054   if (u1 != u2) {
03055     printf("ERROR: Top of undo stack changed. (%d)\n", result);
03056     return NS_ERROR_FAILURE;
03057   }
03058 
03059   result = mgr->PeekRedoStack(&r2);
03060 
03061   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
03062 
03063   if (NS_FAILED(result)) {
03064     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
03065     return result;
03066   }
03067 
03068   if (r1 != r2) {
03069     printf("ERROR: Top of redo stack changed. (%d)\n", result);
03070     return NS_ERROR_FAILURE;
03071   }
03072 
03073   result = mgr->GetNumberOfUndoItems(&numitems);
03074 
03075   if (NS_FAILED(result)) {
03076     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
03077            result);
03078     return result;
03079   }
03080 
03081   if (numitems != 1) {
03082     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
03083            numitems, result);
03084     return NS_ERROR_FAILURE;
03085   }
03086 
03087   result = mgr->GetNumberOfRedoItems(&numitems);
03088 
03089   if (NS_FAILED(result)) {
03090     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
03091            result);
03092     return result;
03093   }
03094 
03095   if (numitems != 0) {
03096     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
03097            numitems, result);
03098     return NS_ERROR_FAILURE;
03099   }
03100 
03101   printf("passed\n");
03102 
03103   /*******************************************************************
03104    *
03105    * Test nested batching. Afterwards, we should have 2 transactions
03106    * on the undo stack:
03107    *
03108    *******************************************************************/
03109 
03110   printf("Test nested batched transactions ... ");
03111 
03112   result = mgr->BeginBatch();
03113 
03114   if (NS_FAILED(result)) {
03115     printf("ERROR: BeginBatch() failed. (%d)\n", result);
03116     return result;
03117   }
03118 
03119   tximpl = factory->create(mgr, NONE_FLAG);
03120 
03121   if (!tximpl) {
03122     printf("ERROR: Failed to allocate transaction.\n");
03123     return NS_ERROR_OUT_OF_MEMORY;
03124   }
03125 
03126   tx = 0;
03127   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
03128   if (NS_FAILED(result)) {
03129     printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);
03130     return result;
03131   }
03132 
03133   result = mgr->DoTransaction(tx);
03134   if (NS_FAILED(result)) {
03135     printf("ERROR: Failed to execute transaction. (%d)\n", result);
03136     return result;
03137   }
03138 
03139   tx->Release();
03140 
03141   result = mgr->GetNumberOfUndoItems(&numitems);
03142 
03143   if (NS_FAILED(result)) {
03144     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
03145            result);
03146     return result;
03147   }
03148 
03149   if (numitems != 1) {
03150     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
03151            numitems, result);
03152     return NS_ERROR_FAILURE;
03153   }
03154 
03155   result = mgr->BeginBatch();
03156 
03157   if (NS_FAILED(result)) {
03158     printf("ERROR: BeginBatch() failed. (%d)\n", result);
03159     return result;
03160   }
03161 
03162   tximpl = factory->create(mgr, NONE_FLAG);
03163 
03164   if (!tximpl) {
03165     printf("ERROR: Failed to allocate transaction.\n");
03166     return NS_ERROR_OUT_OF_MEMORY;
03167   }
03168 
03169   tx = 0;
03170   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
03171   if (NS_FAILED(result)) {
03172     printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);
03173     return result;
03174   }
03175 
03176   result = mgr->DoTransaction(tx);
03177   if (NS_FAILED(result)) {
03178     printf("ERROR: Failed to execute transaction. (%d)\n", result);
03179     return result;
03180   }
03181 
03182   tx->Release();
03183 
03184   result = mgr->GetNumberOfUndoItems(&numitems);
03185 
03186   if (NS_FAILED(result)) {
03187     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
03188            result);
03189     return result;
03190   }
03191 
03192   if (numitems != 1) {
03193     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
03194            numitems, result);
03195     return NS_ERROR_FAILURE;
03196   }
03197 
03198   result = mgr->BeginBatch();
03199 
03200   if (NS_FAILED(result)) {
03201     printf("ERROR: BeginBatch() failed. (%d)\n", result);
03202     return result;
03203   }
03204 
03205   tximpl = factory->create(mgr, NONE_FLAG);
03206 
03207   if (!tximpl) {
03208     printf("ERROR: Failed to allocate transaction.\n");
03209     return NS_ERROR_OUT_OF_MEMORY;
03210   }
03211 
03212   tx = 0;
03213   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
03214   if (NS_FAILED(result)) {
03215     printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);
03216     return result;
03217   }
03218 
03219   result = mgr->DoTransaction(tx);
03220   if (NS_FAILED(result)) {
03221     printf("ERROR: Failed to execute transaction. (%d)\n", result);
03222     return result;
03223   }
03224 
03225   tx->Release();
03226 
03227   result = mgr->GetNumberOfUndoItems(&numitems);
03228 
03229   if (NS_FAILED(result)) {
03230     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
03231            result);
03232     return result;
03233   }
03234 
03235   if (numitems != 1) {
03236     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
03237            numitems, result);
03238     return NS_ERROR_FAILURE;
03239   }
03240 
03241   result = mgr->EndBatch();
03242 
03243   if (NS_FAILED(result)) {
03244     printf("ERROR: EndBatch() failed. (%d)\n", result);
03245     return result;
03246   }
03247 
03248   result = mgr->EndBatch();
03249 
03250   if (NS_FAILED(result)) {
03251     printf("ERROR: EndBatch() failed. (%d)\n", result);
03252     return result;
03253   }
03254 
03255   result = mgr->EndBatch();
03256 
03257   if (NS_FAILED(result)) {
03258     printf("ERROR: EndBatch() failed. (%d)\n", result);
03259     return result;
03260   }
03261 
03262   result = mgr->GetNumberOfUndoItems(&numitems);
03263 
03264   if (NS_FAILED(result)) {
03265     printf("ERROR: GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
03266            result);
03267     return result;
03268   }
03269 
03270   if (numitems != 2) {
03271     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
03272            numitems, result);
03273     return NS_ERROR_FAILURE;
03274   }
03275 
03276   printf("passed\n");
03277 
03278   /*******************************************************************
03279    *
03280    * Undo 2 batch transactions. Afterwards, we should have 0
03281    * transactions on the undo stack and 2 on the redo stack.
03282    *
03283    *******************************************************************/
03284 
03285   printf("Undo 2 batch transactions ... ");
03286 
03287   for (i = 1; i <= 2; ++i) {
03288     result = mgr->UndoTransaction();
03289     if (NS_FAILED(result)) {
03290       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
03291       return result;
03292     }
03293   }
03294 
03295   result = mgr->GetNumberOfUndoItems(&numitems);
03296 
03297   if (NS_FAILED(result)) {
03298     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
03299            result);
03300     return result;
03301   }
03302 
03303   if (numitems != 0) {
03304     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
03305            numitems, result);
03306     return NS_ERROR_FAILURE;
03307   }
03308 
03309   result = mgr->GetNumberOfRedoItems(&numitems);
03310 
03311   if (NS_FAILED(result)) {
03312     printf("ERROR: GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
03313            result);
03314     return result;
03315   }
03316 
03317   if (numitems != 2) {
03318     printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
03319            numitems, result);
03320     return NS_ERROR_FAILURE;
03321   }
03322 
03323   printf("passed\n");
03324 
03325   /*******************************************************************
03326    *
03327    * Redo 2 batch transactions. Afterwards, we should have 2
03328    * transactions on the undo stack and 0 on the redo stack.
03329    *
03330    *******************************************************************/
03331 
03332 
03333   printf("Redo 2 batch transactions ... ");
03334 
03335   for (i = 1; i <= 2; ++i) {
03336     result = mgr->RedoTransaction();
03337     if (NS_FAILED(result)) {
03338       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
03339       return result;
03340     }
03341   }
03342 
03343   result = mgr->GetNumberOfUndoItems(&numitems);
03344 
03345   if (NS_FAILED(result)) {
03346     printf("ERROR: GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
03347            result);
03348     return result;
03349   }
03350 
03351   if (numitems != 2) {
03352     printf("ERROR: GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
03353            numitems, result);
03354     return NS_ERROR_FAILURE;
03355   }
03356 
03357   result = mgr->GetNumberOfRedoItems(&numitems);
03358 
03359   if (NS_FAILED(result)) {
03360     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
03361            result);
03362     return result;
03363   }
03364 
03365   if (numitems != 0) {
03366     printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
03367            numitems, result);
03368     return NS_ERROR_FAILURE;
03369   }
03370 
03371   printf("passed\n");
03372 
03373   /*******************************************************************
03374    *
03375    * Call undo. Afterwards, we should have 1 transaction
03376    * on the undo stack, and 1 on the redo stack:
03377    *
03378    *******************************************************************/
03379 
03380   printf("Undo a batched transaction that was redone ... ");
03381 
03382   result = mgr->UndoTransaction();
03383 
03384   if (NS_FAILED(result)) {
03385     printf("ERROR: Failed to undo transaction. (%d)\n", result);
03386     return result;
03387   }
03388 
03389   result = mgr->GetNumberOfUndoItems(&numitems);
03390 
03391   if (NS_FAILED(result)) {
03392     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
03393            result);
03394     return result;
03395   }
03396 
03397   if (numitems != 1) {
03398     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
03399            numitems, result);
03400     return NS_ERROR_FAILURE;
03401   }
03402 
03403   result = mgr->GetNumberOfRedoItems(&numitems);
03404 
03405   if (NS_FAILED(result)) {
03406     printf("ERROR: GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
03407            result);
03408     return result;
03409   }
03410 
03411   if (numitems != 1) {
03412     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
03413            numitems, result);
03414     return NS_ERROR_FAILURE;
03415   }
03416 
03417   printf("passed\n");
03418 
03419   /*******************************************************************
03420    *
03421    * Make sure an unbalanced call to EndBatch() throws an error and
03422    * doesn't affect the undo and redo stacks!
03423    *
03424    *******************************************************************/
03425 
03426   printf("Test effect of unbalanced EndBatch() on undo and redo stacks ... ");
03427 
03428   result = mgr->EndBatch();
03429 
03430   if (result != NS_ERROR_FAILURE) {
03431     printf("ERROR: EndBatch() returned unexpected status. (%d)\n", result);
03432     return result;
03433   }
03434 
03435   result = mgr->GetNumberOfUndoItems(&numitems);
03436 
03437   if (NS_FAILED(result)) {
03438     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
03439            result);
03440     return result;
03441   }
03442 
03443   if (numitems != 1) {
03444     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
03445            numitems, result);
03446     return NS_ERROR_FAILURE;
03447   }
03448 
03449   result = mgr->GetNumberOfRedoItems(&numitems);
03450 
03451   if (NS_FAILED(result)) {
03452     printf("ERROR: GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
03453            result);
03454     return result;
03455   }
03456 
03457   if (numitems != 1) {
03458     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
03459            numitems, result);
03460     return NS_ERROR_FAILURE;
03461   }
03462 
03463   printf("passed\n");
03464 
03465   /*******************************************************************
03466    *
03467    * Make sure that an empty batch is not added to the undo stack
03468    * when it is closed, and that it does not affect the undo and redo
03469    * stacks.
03470    *
03471    *******************************************************************/
03472 
03473   printf("Test effect of empty batch on undo and redo stacks ... ");
03474 
03475   result = mgr->BeginBatch();
03476 
03477   if (NS_FAILED(result)) {
03478     printf("ERROR: BeginBatch() failed. (%d)\n", result);
03479     return result;
03480   }
03481 
03482   result = mgr->GetNumberOfUndoItems(&numitems);
03483 
03484   if (NS_FAILED(result)) {
03485     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
03486            result);
03487     return result;
03488   }
03489 
03490   if (numitems != 1) {
03491     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
03492            numitems, result);
03493     return NS_ERROR_FAILURE;
03494   }
03495 
03496   result = mgr->GetNumberOfRedoItems(&numitems);
03497 
03498   if (NS_FAILED(result)) {
03499     printf("ERROR: GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
03500            result);
03501     return result;
03502   }
03503 
03504   if (numitems != 1) {
03505     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
03506            numitems, result);
03507     return NS_ERROR_FAILURE;
03508   }
03509 
03510   result = mgr->EndBatch();
03511 
03512   if (NS_FAILED(result)) {
03513     printf("ERROR: EndBatch() failed. (%d)\n", result);
03514     return result;
03515   }
03516 
03517   result = mgr->GetNumberOfUndoItems(&numitems);
03518 
03519   if (NS_FAILED(result)) {
03520     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
03521            result);
03522     return result;
03523   }
03524 
03525   if (numitems != 1) {
03526     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
03527            numitems, result);
03528     return NS_ERROR_FAILURE;
03529   }
03530 
03531   result = mgr->GetNumberOfRedoItems(&numitems);
03532 
03533   if (NS_FAILED(result)) {
03534     printf("ERROR: GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
03535            result);
03536     return result;
03537   }
03538 
03539   if (numitems != 1) {
03540     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
03541            numitems, result);
03542     return NS_ERROR_FAILURE;
03543   }
03544 
03545 
03546   printf("passed\n");
03547 
03548 
03549   /*******************************************************************
03550    *
03551    * Execute a new transaction. The redo stack should get pruned!
03552    *
03553    *******************************************************************/
03554 
03555   printf("Check if new batched transactions prune the redo stack ... ");
03556 
03557   result = mgr->BeginBatch();
03558 
03559   if (NS_FAILED(result)) {
03560     printf("ERROR: BeginBatch() failed. (%d)\n", result);
03561     return result;
03562   }
03563 
03564   for (i = 1; i <= 20; i++) {
03565     tximpl = factory->create(mgr, NONE_FLAG);
03566 
03567     if (!tximpl) {
03568       printf("ERROR: Failed to allocate transaction %d.\n", i);
03569       return NS_ERROR_OUT_OF_MEMORY;
03570     }
03571 
03572     tx = 0;
03573     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
03574     if (NS_FAILED(result)) {
03575       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
03576              i, result);
03577       return result;
03578     }
03579 
03580     result = mgr->DoTransaction(tx);
03581     if (NS_FAILED(result)) {
03582       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
03583       return result;
03584     }
03585 
03586     tx->Release();
03587   }
03588 
03589   result = mgr->GetNumberOfUndoItems(&numitems);
03590 
03591   if (NS_FAILED(result)) {
03592     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
03593            result);
03594     return result;
03595   }
03596 
03597   if (numitems != 1) {
03598     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
03599            numitems, result);
03600     return NS_ERROR_FAILURE;
03601   }
03602 
03603   result = mgr->GetNumberOfRedoItems(&numitems);
03604 
03605   if (NS_FAILED(result)) {
03606     printf("ERROR: GetNumberOfRedoItems() on redo stack with 1 items failed. (%d)\n",
03607            result);
03608     return result;
03609   }
03610 
03611   if (numitems != 1) {
03612     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
03613            numitems, result);
03614     return NS_ERROR_FAILURE;
03615   }
03616 
03617   result = mgr->EndBatch();
03618 
03619   if (NS_FAILED(result)) {
03620     printf("ERROR: EndBatch() failed. (%d)\n", result);
03621     return result;
03622   }
03623 
03624   result = mgr->GetNumberOfUndoItems(&numitems);
03625 
03626   if (NS_FAILED(result)) {
03627     printf("ERROR: GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
03628            result);
03629     return result;
03630   }
03631 
03632   if (numitems != 2) {
03633     printf("ERROR: GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
03634            numitems, result);
03635     return NS_ERROR_FAILURE;
03636   }
03637 
03638   result = mgr->GetNumberOfRedoItems(&numitems);
03639 
03640   if (NS_FAILED(result)) {
03641     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
03642            result);
03643     return result;
03644   }
03645 
03646   if (numitems != 0) {
03647     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
03648            numitems, result);
03649     return NS_ERROR_FAILURE;
03650   }
03651 
03652   printf("passed\n");
03653 
03654   /*******************************************************************
03655    *
03656    * Call undo.
03657    *
03658    *******************************************************************/
03659 
03660   printf("Call undo ... ");
03661 
03662   // Move a transaction over to the redo stack, so that we have one
03663   // transaction on the undo stack, and one on the redo stack!
03664 
03665   result = mgr->UndoTransaction();
03666 
03667   if (NS_FAILED(result)) {
03668     printf("ERROR: Failed to undo transaction. (%d)\n", result);
03669     return result;
03670   }
03671 
03672   result = mgr->GetNumberOfUndoItems(&numitems);
03673 
03674   if (NS_FAILED(result)) {
03675     printf("ERROR: GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
03676            result);
03677     return result;
03678   }
03679 
03680   if (numitems != 1) {
03681     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
03682            numitems, result);
03683     return NS_ERROR_FAILURE;
03684   }
03685 
03686   result = mgr->GetNumberOfRedoItems(&numitems);
03687 
03688   if (NS_FAILED(result)) {
03689     printf("ERROR: GetNumberOfRedoItems() on redo stack with 1 items failed. (%d)\n",
03690            result);
03691     return result;
03692   }
03693 
03694   if (numitems != 1) {
03695     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
03696            numitems, result);
03697     return NS_ERROR_FAILURE;
03698   }
03699 
03700   printf("passed\n");
03701 
03702   /*******************************************************************
03703    *
03704    * Test transaction DoTransaction() error:
03705    *
03706    *******************************************************************/
03707 
03708   printf("Test transaction DoTransaction() error ... ");
03709 
03710 
03711   tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
03712 
03713   if (!tximpl) {
03714     printf("ERROR: Failed to allocate transaction.\n");
03715     return NS_ERROR_OUT_OF_MEMORY;
03716   }
03717 
03718   tx     = 0;
03719 
03720   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
03721 
03722   if (NS_FAILED(result)) {
03723     printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);
03724     return result;
03725   }
03726 
03727   u1 = u2 = r1 = r2 = 0;
03728 
03729   result = mgr->PeekUndoStack(&u1);
03730 
03731   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
03732 
03733   if (NS_FAILED(result)) {
03734     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
03735     return result;
03736   }
03737 
03738   result = mgr->PeekRedoStack(&r1);
03739 
03740   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
03741 
03742   if (NS_FAILED(result)) {
03743     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
03744     return result;
03745   }
03746 
03747   result = mgr->BeginBatch();
03748 
03749   if (NS_FAILED(result)) {
03750     printf("ERROR: BeginBatch() failed. (%d)\n", result);
03751     return result;
03752   }
03753 
03754   result = mgr->DoTransaction(tx);
03755 
03756   if (NS_FAILED(result) && result != NS_ERROR_FAILURE) {
03757     printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);
03758     return result;
03759   }
03760 
03761   tx->Release();
03762 
03763   result = mgr->EndBatch();
03764 
03765   if (NS_FAILED(result)) {
03766     printf("ERROR: EndBatch() failed. (%d)\n", result);
03767     return result;
03768   }
03769 
03770   result = mgr->PeekUndoStack(&u2);
03771 
03772   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
03773 
03774   if (NS_FAILED(result)) {
03775     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
03776     return result;
03777   }
03778 
03779   if (u1 != u2) {
03780     printf("ERROR: Top of undo stack changed. (%d)\n", result);
03781     return NS_ERROR_FAILURE;
03782   }
03783 
03784   result = mgr->PeekRedoStack(&r2);
03785 
03786   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
03787 
03788   if (NS_FAILED(result)) {
03789     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
03790     return result;
03791   }
03792 
03793   if (r1 != r2) {
03794     printf("ERROR: Top of redo stack changed. (%d)\n", result);
03795     return NS_ERROR_FAILURE;
03796   }
03797 
03798   result = mgr->GetNumberOfUndoItems(&numitems);
03799 
03800   if (NS_FAILED(result)) {
03801     printf("ERROR: GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
03802            result);
03803     return result;
03804   }
03805 
03806   if (numitems != 1) {
03807     printf("ERROR: GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
03808            numitems, result);
03809     return NS_ERROR_FAILURE;
03810   }
03811 
03812   result = mgr->GetNumberOfRedoItems(&numitems);
03813 
03814   if (NS_FAILED(result)) {
03815     printf("ERROR: GetNumberOfRedoItems() on empty redo stack. (%d)\n",
03816            result);
03817     return result;
03818   }
03819 
03820   if (numitems != 1) {
03821     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
03822            numitems, result);
03823     return NS_ERROR_FAILURE;
03824   }
03825 
03826   printf("passed\n");
03827 
03828   /*******************************************************************
03829    *
03830    * Test transaction UndoTransaction() error:
03831    *
03832    *******************************************************************/
03833 
03834   printf("Test transaction UndoTransaction() error ... ");
03835 
03836   tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
03837 
03838   if (!tximpl) {
03839     printf("ERROR: Failed to allocate transaction.\n");
03840     return NS_ERROR_OUT_OF_MEMORY;
03841   }
03842 
03843   tx     = 0;
03844 
03845   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
03846 
03847   if (NS_FAILED(result)) {
03848     printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);
03849     return result;
03850   }
03851 
03852   result = mgr->BeginBatch();
03853 
03854   if (NS_FAILED(result)) {
03855     printf("ERROR: BeginBatch() failed. (%d)\n", result);
03856     return result;
03857   }
03858 
03859   result = mgr->DoTransaction(tx);
03860 
03861   if (NS_FAILED(result)) {
03862     printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);
03863     return result;
03864   }
03865 
03866   tx->Release();
03867 
03868   result = mgr->EndBatch();
03869 
03870   if (NS_FAILED(result)) {
03871     printf("ERROR: EndBatch() failed. (%d)\n", result);
03872     return result;
03873   }
03874 
03875   u1 = u2 = r1 = r2 = 0;
03876 
03877   result = mgr->PeekUndoStack(&u1);
03878 
03879   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
03880 
03881   if (NS_FAILED(result)) {
03882     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
03883     return result;
03884   }
03885 
03886   result = mgr->PeekRedoStack(&r1);
03887 
03888   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
03889 
03890   if (NS_FAILED(result)) {
03891     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
03892     return result;
03893   }
03894 
03895   result = mgr->UndoTransaction();
03896 
03897   if (NS_FAILED(result) && result != NS_ERROR_FAILURE) {
03898     printf("ERROR: UndoTransaction() returned unexpected error. (%d)\n", result);
03899     return result;
03900   }
03901 
03902   result = mgr->PeekUndoStack(&u2);
03903 
03904   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
03905 
03906   if (NS_FAILED(result)) {
03907     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
03908     return result;
03909   }
03910 
03911   if (u1 != u2) {
03912     printf("ERROR: Top of undo stack changed. (%d)\n", result);
03913     return NS_ERROR_FAILURE;
03914   }
03915 
03916   result = mgr->PeekRedoStack(&r2);
03917 
03918   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
03919 
03920   if (NS_FAILED(result)) {
03921     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
03922     return result;
03923   }
03924 
03925   if (r1 != r2) {
03926     printf("ERROR: Top of redo stack changed. (%d)\n", result);
03927     return NS_ERROR_FAILURE;
03928   }
03929 
03930   result = mgr->GetNumberOfUndoItems(&numitems);
03931 
03932   if (NS_FAILED(result)) {
03933     printf("ERROR: GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
03934            result);
03935     return result;
03936   }
03937 
03938   if (numitems != 2) {
03939     printf("ERROR: GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
03940            numitems, result);
03941     return NS_ERROR_FAILURE;
03942   }
03943 
03944   result = mgr->GetNumberOfRedoItems(&numitems);
03945 
03946   if (NS_FAILED(result)) {
03947     printf("ERROR: GetNumberOfRedoItems() on empty redo stack. (%d)\n",
03948            result);
03949     return result;
03950   }
03951 
03952   if (numitems != 0) {
03953     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
03954            numitems, result);
03955     return NS_ERROR_FAILURE;
03956   }
03957 
03958   printf("passed\n");
03959 
03960   /*******************************************************************
03961    *
03962    * Test transaction RedoTransaction() error:
03963    *
03964    *******************************************************************/
03965 
03966   printf("Test transaction RedoTransaction() error ... ");
03967 
03968   tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
03969 
03970   if (!tximpl) {
03971     printf("ERROR: Failed to allocate transaction.\n");
03972     return NS_ERROR_OUT_OF_MEMORY;
03973   }
03974 
03975   tx     = 0;
03976 
03977   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
03978 
03979   if (NS_FAILED(result)) {
03980     printf("ERROR: QueryInterface() failed for RedoErrorTransaction. (%d)\n",
03981            result);
03982     return result;
03983   }
03984 
03985   result = mgr->BeginBatch();
03986 
03987   if (NS_FAILED(result)) {
03988     printf("ERROR: BeginBatch() failed. (%d)\n", result);
03989     return result;
03990   }
03991 
03992   result = mgr->DoTransaction(tx);
03993 
03994   if (NS_FAILED(result)) {
03995     printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);
03996     return result;
03997   }
03998 
03999   tx->Release();
04000 
04001   result = mgr->EndBatch();
04002 
04003   if (NS_FAILED(result)) {
04004     printf("ERROR: EndBatch() failed. (%d)\n", result);
04005     return result;
04006   }
04007 
04008   //
04009   // Execute a normal transaction to be used in a later test:
04010   //
04011 
04012   tximpl = factory->create(mgr, NONE_FLAG);
04013 
04014   if (!tximpl) {
04015     printf("ERROR: Failed to allocate transaction.\n");
04016     return NS_ERROR_OUT_OF_MEMORY;
04017   }
04018 
04019   tx     = 0;
04020 
04021   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
04022 
04023   if (NS_FAILED(result)) {
04024     printf("ERROR: QueryInterface() failed for transaction. (%d)\n", result);
04025     return result;
04026   }
04027 
04028   result = mgr->DoTransaction(tx);
04029 
04030   if (NS_FAILED(result)) {
04031     printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);
04032     return result;
04033   }
04034 
04035   tx->Release();
04036 
04037   //
04038   // Undo the 2 transactions just executed.
04039   //
04040 
04041   for (i = 1; i <= 2; ++i) {
04042     result = mgr->UndoTransaction();
04043     if (NS_FAILED(result)) {
04044       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
04045       return result;
04046     }
04047   }
04048 
04049   //
04050   // The RedoErrorTransaction should now be at the top of the redo stack!
04051   //
04052 
04053   u1 = u2 = r1 = r2 = 0;
04054 
04055   result = mgr->PeekUndoStack(&u1);
04056 
04057   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
04058 
04059   if (NS_FAILED(result)) {
04060     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
04061     return result;
04062   }
04063 
04064   result = mgr->PeekRedoStack(&r1);
04065 
04066   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
04067 
04068   if (NS_FAILED(result)) {
04069     printf("ERROR: Initial PeekRedoStack() failed. (%d)\n", result);
04070     return result;
04071   }
04072 
04073   result = mgr->RedoTransaction();
04074 
04075   if (NS_FAILED(result) && result != NS_ERROR_FAILURE) {
04076     printf("ERROR: RedoTransaction() returned unexpected error. (%d)\n", result);
04077     return result;
04078   }
04079 
04080   result = mgr->PeekUndoStack(&u2);
04081 
04082   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
04083 
04084   if (NS_FAILED(result)) {
04085     printf("ERROR: Second PeekUndoStack() failed. (%d)\n", result);
04086     return result;
04087   }
04088 
04089   if (u1 != u2) {
04090     printf("ERROR: Top of undo stack changed. (%d)\n", result);
04091     return NS_ERROR_FAILURE;
04092   }
04093 
04094   result = mgr->PeekRedoStack(&r2);
04095 
04096   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
04097 
04098   if (NS_FAILED(result)) {
04099     printf("ERROR: Second PeekRedoStack() failed. (%d)\n", result);
04100     return result;
04101   }
04102 
04103   if (r1 != r2) {
04104     printf("ERROR: Top of redo stack changed. (%d)\n", result);
04105     return NS_ERROR_FAILURE;
04106   }
04107 
04108   result = mgr->GetNumberOfUndoItems(&numitems);
04109 
04110   if (NS_FAILED(result)) {
04111     printf("ERROR: GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
04112            result);
04113     return result;
04114   }
04115 
04116   if (numitems != 2) {
04117     printf("ERROR: GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
04118            numitems, result);
04119     return NS_ERROR_FAILURE;
04120   }
04121 
04122   result = mgr->GetNumberOfRedoItems(&numitems);
04123 
04124   if (NS_FAILED(result)) {
04125     printf("ERROR: GetNumberOfRedoItems() on empty redo stack. (%d)\n",
04126            result);
04127     return result;
04128   }
04129 
04130   if (numitems != 2) {
04131     printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
04132            numitems, result);
04133     return NS_ERROR_FAILURE;
04134   }
04135 
04136   printf("passed\n");
04137 
04138   /*******************************************************************
04139    *
04140    * Make sure that setting the transaction manager's max transaction
04141    * count to zero, clears both the undo and redo stacks, and executes
04142    * all new commands without pushing them on the undo stack!
04143    *
04144    *******************************************************************/
04145 
04146   printf("Test max transaction count of zero ... ");
04147 
04148   result = mgr->SetMaxTransactionCount(0);
04149 
04150   if (NS_FAILED(result)) {
04151     printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);
04152     return result;
04153   }
04154 
04155   result = mgr->GetNumberOfUndoItems(&numitems);
04156 
04157   if (NS_FAILED(result)) {
04158     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
04159            result);
04160     return result;
04161   }
04162 
04163   if (numitems != 0) {
04164     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
04165            numitems, result);
04166     return NS_ERROR_FAILURE;
04167   }
04168 
04169   result = mgr->GetNumberOfRedoItems(&numitems);
04170 
04171   if (NS_FAILED(result)) {
04172     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
04173            result);
04174     return result;
04175   }
04176 
04177   if (numitems != 0) {
04178     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
04179            numitems, result);
04180     return NS_ERROR_FAILURE;
04181   }
04182 
04183   for (i = 1; i <= 20; i++) {
04184     tximpl = factory->create(mgr, NONE_FLAG);
04185 
04186     if (!tximpl) {
04187       printf("ERROR: Failed to allocate transaction %d.\n", i);
04188       return NS_ERROR_OUT_OF_MEMORY;
04189     }
04190 
04191     tx = 0;
04192     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
04193     if (NS_FAILED(result)) {
04194       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
04195              i, result);
04196       return result;
04197     }
04198 
04199     result = mgr->BeginBatch();
04200 
04201     if (NS_FAILED(result)) {
04202       printf("ERROR: BeginBatch() failed. (%d)\n", result);
04203       return result;
04204     }
04205 
04206     result = mgr->DoTransaction(tx);
04207     if (NS_FAILED(result)) {
04208       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
04209       return result;
04210     }
04211 
04212     tx->Release();
04213 
04214     result = mgr->EndBatch();
04215 
04216     if (NS_FAILED(result)) {
04217       printf("ERROR: EndBatch() failed. (%d)\n", result);
04218       return result;
04219     }
04220 
04221     result = mgr->GetNumberOfUndoItems(&numitems);
04222 
04223     if (NS_FAILED(result)) {
04224       printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
04225              result);
04226       return result;
04227     }
04228 
04229     if (numitems != 0) {
04230       printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
04231              numitems, result);
04232       return NS_ERROR_FAILURE;
04233     }
04234 
04235     result = mgr->GetNumberOfRedoItems(&numitems);
04236 
04237     if (NS_FAILED(result)) {
04238       printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
04239              result);
04240       return result;
04241     }
04242 
04243     if (numitems != 0) {
04244       printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
04245              numitems, result);
04246       return NS_ERROR_FAILURE;
04247     }
04248   }
04249 
04250   printf("passed\n");
04251 
04252   /*******************************************************************
04253    *
04254    * Release the transaction manager. Any transactions on the undo
04255    * and redo stack should automatically be released:
04256    *
04257    *******************************************************************/
04258 
04259   printf("Release the transaction manager ... ");
04260 
04261   result = mgr->SetMaxTransactionCount(-1);
04262 
04263   if (NS_FAILED(result)) {
04264     printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);
04265     return result;
04266   }
04267 
04268   // Push 20 transactions on the undo stack:
04269 
04270   for (i = 1; i <= 20; i++) {
04271     tximpl = factory->create(mgr, NONE_FLAG);
04272 
04273     if (!tximpl) {
04274       printf("ERROR: Failed to allocate transaction %d.\n", i);
04275       return NS_ERROR_OUT_OF_MEMORY;
04276     }
04277 
04278     tx = 0;
04279     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
04280     if (NS_FAILED(result)) {
04281       printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
04282              i, result);
04283       return result;
04284     }
04285 
04286     result = mgr->BeginBatch();
04287 
04288     if (NS_FAILED(result)) {
04289       printf("ERROR: BeginBatch() failed. (%d)\n", result);
04290       return result;
04291     }
04292 
04293     result = mgr->DoTransaction(tx);
04294     if (NS_FAILED(result)) {
04295       printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
04296       return result;
04297     }
04298 
04299     tx->Release();
04300 
04301     result = mgr->EndBatch();
04302 
04303     if (NS_FAILED(result)) {
04304       printf("ERROR: EndBatch() failed. (%d)\n", result);
04305       return result;
04306     }
04307 
04308     result = mgr->GetNumberOfUndoItems(&numitems);
04309 
04310     if (NS_FAILED(result)) {
04311       printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
04312              result);
04313       return result;
04314     }
04315 
04316     if (numitems != i) {
04317       printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
04318              numitems, result);
04319       return NS_ERROR_FAILURE;
04320     }
04321 
04322     result = mgr->GetNumberOfRedoItems(&numitems);
04323 
04324     if (NS_FAILED(result)) {
04325       printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
04326              result);
04327       return result;
04328     }
04329 
04330     if (numitems != 0) {
04331       printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
04332              numitems, result);
04333       return NS_ERROR_FAILURE;
04334     }
04335   }
04336 
04337   for (i = 1; i <= 10; i++) {
04338 
04339     result = mgr->UndoTransaction();
04340     if (NS_FAILED(result)) {
04341       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
04342       return result;
04343     }
04344   }
04345   result = mgr->GetNumberOfUndoItems(&numitems);
04346 
04347   if (NS_FAILED(result)) {
04348     printf("ERROR: GetNumberOfUndoItems() on empty undo stack with 10 items failed. (%d)\n",
04349            result);
04350     return result;
04351   }
04352 
04353   if (numitems != 10) {
04354     printf("ERROR: GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
04355            numitems, result);
04356     return NS_ERROR_FAILURE;
04357   }
04358 
04359   result = mgr->GetNumberOfRedoItems(&numitems);
04360 
04361   if (NS_FAILED(result)) {
04362     printf("ERROR: GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
04363            result);
04364     return result;
04365   }
04366 
04367   if (numitems != 10) {
04368     printf("ERROR: GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
04369            numitems, result);
04370     return NS_ERROR_FAILURE;
04371   }
04372 
04373   printf("passed\n");
04374 
04375   /*******************************************************************
04376    *
04377    * Make sure number of transactions created matches number of
04378    * transactions destroyed!
04379    *
04380    *******************************************************************/
04381 
04382   printf("Number of transactions created and destroyed match ... ");
04383 
04384   if (sConstructorCount != sDestructorCount) {
04385     printf("ERROR: Transaction constructor count (%d) != destructor count (%d).\n",
04386            sConstructorCount, sDestructorCount);
04387     return NS_ERROR_FAILURE;
04388   }
04389 
04390   if (NS_FAILED(result)) {
04391     printf("ERROR: nsITransactionManager Release() failed. (%d)\n", result);
04392     return result;
04393   }
04394 
04395   printf("passed\n");
04396   printf("%d transactions processed during quick batch test.\n",
04397          sConstructorCount);
04398 
04399   return NS_OK;
04400 }
04401 
04402 nsresult
04403 simple_batch_test()
04404 {
04405   /*******************************************************************
04406    *
04407    * Initialize globals for test.
04408    *
04409    *******************************************************************/
04410   reset_globals();
04411   sDestructorOrderArr = sSimpleBatchTestDestructorOrderArr;
04412   sDoOrderArr         = sSimpleBatchTestDoOrderArr;
04413   sUndoOrderArr       = sSimpleBatchTestUndoOrderArr;
04414   sRedoOrderArr       = sSimpleBatchTestRedoOrderArr;
04415 
04416   /*******************************************************************
04417    *
04418    * Run the quick batch test.
04419    *
04420    *******************************************************************/
04421 
04422   SimpleTransactionFactory factory;
04423 
04424   printf("\n-----------------------------------------------------\n");
04425   printf("- Begin Batch Transaction Test:\n");
04426   printf("-----------------------------------------------------\n");
04427 
04428   return quick_batch_test(&factory);
04429 }
04430 
04431 nsresult
04432 aggregation_batch_test()
04433 {
04434   /*******************************************************************
04435    *
04436    * Initialize globals for test.
04437    *
04438    *******************************************************************/
04439 
04440   reset_globals();
04441   sDestructorOrderArr = sAggregateBatchTestDestructorOrderArr;
04442   sDoOrderArr         = sAggregateBatchTestDoOrderArr;
04443   sUndoOrderArr       = sAggregateBatchTestUndoOrderArr;
04444   sRedoOrderArr       = sAggregateBatchTestRedoOrderArr;
04445 
04446   /*******************************************************************
04447    *
04448    * Run the quick batch test.
04449    *
04450    *******************************************************************/
04451 
04452   AggregateTransactionFactory factory(3,2,BATCH_FLAG);
04453 
04454   printf("\n-----------------------------------------------------\n");
04455   printf("- Begin Batch Aggregate Transaction Test:\n");
04456   printf("-----------------------------------------------------\n");
04457 
04458   return quick_batch_test(&factory);
04459 }
04460 
04461 nsresult
04462 stress_test(TestTransactionFactory *factory, PRInt32 iterations)
04463 {
04464   /*******************************************************************
04465    *
04466    * Create a transaction manager:
04467    *
04468    *******************************************************************/
04469 
04470   printf("Stress test (may take a while) ... ");
04471   fflush(stdout);
04472 
04473   PRInt32 i, j;
04474   nsCOMPtr<nsITransactionManager> mgr;
04475   nsITransaction *tx          = 0;
04476   nsresult result;
04477 
04478   mgr = do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
04479   if (NS_FAILED(result) || !mgr) {
04480     printf("ERROR: Failed to create Transaction Manager instance.\n");
04481     return NS_ERROR_OUT_OF_MEMORY;
04482   }
04483 
04484   for (i = 1; i <= iterations; i++) {
04485     /*******************************************************************
04486      *
04487      * Execute a bunch of transactions:
04488      *
04489      *******************************************************************/
04490 
04491     for (j = 1; j <= i; j++) {
04492       TestTransaction *tximpl = factory->create(mgr, NONE_FLAG);
04493 
04494       if (!tximpl) {
04495         printf("ERROR: Failed to allocate transaction %d.\n", j);
04496         return NS_ERROR_OUT_OF_MEMORY;
04497       }
04498 
04499       tx = 0;
04500       result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
04501       if (NS_FAILED(result)) {
04502         printf("ERROR: QueryInterface() failed for transaction %d. (%d)\n",
04503                i, result);
04504         return result;
04505       }
04506 
04507       result = mgr->DoTransaction(tx);
04508       if (NS_FAILED(result)) {
04509         printf("ERROR: Failed to execute transaction %d. (%d)\n", i, result);
04510         return result;
04511       }
04512 
04513       tx->Release();
04514     }
04515 
04516     /*******************************************************************
04517      *
04518      * Undo all the transactions:
04519      *
04520      *******************************************************************/
04521 
04522     for (j = 1; j <= i; j++) {
04523       result = mgr->UndoTransaction();
04524       if (NS_FAILED(result)) {
04525         printf("ERROR: Failed to undo transaction %d-%d. (%d)\n", i, j, result);
04526         return result;
04527       }
04528     }
04529 
04530     /*******************************************************************
04531      *
04532      * Redo all the transactions:
04533      *
04534      *******************************************************************/
04535 
04536     for (j = 1; j <= i; j++) {
04537       result = mgr->RedoTransaction();
04538       if (NS_FAILED(result)) {
04539         printf("ERROR: Failed to redo transaction %d-%d. (%d)\n", i, j, result);
04540         return result;
04541       }
04542     }
04543 
04544     /*******************************************************************
04545      *
04546      * Undo all the transactions again so that they all end up on
04547      * the redo stack for pruning the next time we execute a new
04548      * transaction
04549      *
04550      *******************************************************************/
04551 
04552     for (j = 1; j <= i; j++) {
04553       result = mgr->UndoTransaction();
04554       if (NS_FAILED(result)) {
04555         printf("ERROR: Failed to undo transaction %d-%d. (%d)\n", i, j, result);
04556         return result;
04557       }
04558     }
04559   }
04560 
04561   // printf("%d  %d -  ", sConstructorCount, sDestructorCount);
04562 
04563   if (sConstructorCount != sDestructorCount) {
04564     printf("ERROR: Transaction constructor count (%d) != destructor count (%d).\n",
04565            sConstructorCount, sDestructorCount);
04566     return NS_ERROR_FAILURE;
04567   }
04568 
04569   printf("passed\n");
04570 
04571   printf("%d transactions processed during stress test.\n", sConstructorCount);
04572 
04573   return NS_OK;
04574 }
04575 
04576 nsresult
04577 simple_stress_test()
04578 {
04579   /*******************************************************************
04580    *
04581    * Initialize globals for test.
04582    *
04583    *******************************************************************/
04584 
04585   reset_globals();
04586 
04587   /*******************************************************************
04588    *
04589    * Do the stress test:
04590    *
04591    *******************************************************************/
04592 
04593   SimpleTransactionFactory factory;
04594 
04595   printf("\n-----------------------------------------------------\n");
04596   printf("- Simple Transaction Stress Test:\n");
04597   printf("-----------------------------------------------------\n");
04598 
04599   //
04600   // 1500 iterations sends 1,125,750 transactions through the system!!
04601   //
04602   return stress_test(&factory, 1500);
04603 }
04604 
04605 nsresult
04606 aggregation_stress_test()
04607 {
04608   /*******************************************************************
04609    *
04610    * Initialize globals for test.
04611    *
04612    *******************************************************************/
04613 
04614   reset_globals();
04615 
04616   /*******************************************************************
04617    *
04618    * Do the stress test:
04619    *
04620    *******************************************************************/
04621 
04622   AggregateTransactionFactory factory(3,4);
04623 
04624   printf("\n-----------------------------------------------------\n");
04625   printf("- Aggregate Transaction Stress Test:\n");
04626   printf("-----------------------------------------------------\n");
04627 
04628   //
04629   // 500 iterations sends 2,630,250 transactions through the system!!
04630   //
04631   return stress_test(&factory, 500);
04632 }
04633 
04634 nsresult
04635 aggregation_batch_stress_test()
04636 {
04637   /*******************************************************************
04638    *
04639    * Initialize globals for test.
04640    *
04641    *******************************************************************/
04642 
04643   reset_globals();
04644 
04645   /*******************************************************************
04646    *
04647    * Do the stress test:
04648    *
04649    *******************************************************************/
04650 
04651   AggregateTransactionFactory factory(3,4,BATCH_FLAG);
04652 
04653   printf("\n-----------------------------------------------------\n");
04654   printf("- Aggregate Batch Transaction Stress Test:\n");
04655   printf("-----------------------------------------------------\n");
04656 
04657   //
04658   // 500 iterations sends 2,630,250 transactions through the system!!
04659   //
04660   return stress_test(&factory, 500);
04661 }
04662 
04663 int
04664 main (int argc, char *argv[])
04665 {
04666   nsresult result = NS_InitXPCOM2(nsnull, nsnull, nsnull);
04667   if (NS_FAILED(result))
04668     return result;
04669 
04670   result = simple_test();
04671 
04672   if (NS_FAILED(result))
04673     return result;
04674 
04675   result = simple_batch_test();
04676 
04677   if (NS_FAILED(result))
04678     return result;
04679 
04680   result = aggregation_test();
04681 
04682   if (NS_FAILED(result))
04683     return result;
04684 
04685   result = aggregation_batch_test();
04686 
04687   if (NS_FAILED(result))
04688     return result;
04689 
04690   result = simple_stress_test();
04691 
04692   if (NS_FAILED(result))
04693     return result;
04694 
04695   result = aggregation_stress_test();
04696 
04697   if (NS_FAILED(result))
04698     return result;
04699 
04700   result = aggregation_batch_stress_test();
04701 
04702   if (NS_FAILED(result))
04703     return result;
04704 
04705   return NS_OK;
04706 }