editor/txmgr/tests/TestTXMgr.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/editor/txmgr/tests/TestTXMgr.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,4638 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "TestHarness.h"
    1.10 +
    1.11 +#include "nsITransactionManager.h"
    1.12 +#include "nsComponentManagerUtils.h"
    1.13 +#include "mozilla/Likely.h"
    1.14 +
    1.15 +static int32_t sConstructorCount     = 0;
    1.16 +static int32_t sDestructorCount      = 0;
    1.17 +static int32_t *sDestructorOrderArr  = 0;
    1.18 +static int32_t sDoCount              = 0;
    1.19 +static int32_t *sDoOrderArr          = 0;
    1.20 +static int32_t sUndoCount            = 0;
    1.21 +static int32_t *sUndoOrderArr        = 0;
    1.22 +static int32_t sRedoCount            = 0;
    1.23 +static int32_t *sRedoOrderArr        = 0;
    1.24 +
    1.25 +// #define ENABLE_DEBUG_PRINTFS 1
    1.26 +
    1.27 +int32_t sSimpleTestDestructorOrderArr[] = {
    1.28 +          2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,
    1.29 +         16,  17,  18,  19,  20,  21,   1,  22,  23,  24,  25,  26,  27,  28,
    1.30 +         29,  30,  31,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,
    1.31 +         53,  54,  55,  56,  57,  58,  59,  60,  61,  41,  40,  62,  39,  38,
    1.32 +         37,  36,  35,  34,  33,  32,  68,  63,  64,  65,  66,  67,  69,  71,
    1.33 +         70,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
    1.34 +         85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
    1.35 +         99, 100, 101, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 131,
    1.36 +        130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117,
    1.37 +        116, 115, 114, 113, 112 };
    1.38 +
    1.39 +int32_t sSimpleTestDoOrderArr[] = {
    1.40 +          1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
    1.41 +         15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
    1.42 +         29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
    1.43 +         43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
    1.44 +         57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
    1.45 +         71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
    1.46 +         85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
    1.47 +         99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
    1.48 +        113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
    1.49 +        127, 128, 129, 130, 131 };
    1.50 +
    1.51 +int32_t sSimpleTestUndoOrderArr[] = {
    1.52 +         41,  40,  39,  38,  62,  39,  38,  37,  69,  71,  70, 111, 110, 109,
    1.53 +        108, 107, 106, 105, 104, 103, 102, 131, 130, 129, 128, 127, 126, 125,
    1.54 +        124, 123, 122 };
    1.55 +
    1.56 +static int32_t sSimpleTestRedoOrderArr[] = {
    1.57 +         38,  39,  70 };
    1.58 +
    1.59 +int32_t sAggregateTestDestructorOrderArr[] = {
    1.60 +         14,  13,  12,  11,  10,   9,   8,  21,  20,  19,  18,  17,  16,  15,
    1.61 +         28,  27,  26,  25,  24,  23,  22,  35,  34,  33,  32,  31,  30,  29,
    1.62 +         42,  41,  40,  39,  38,  37,  36,  49,  48,  47,  46,  45,  44,  43,
    1.63 +         56,  55,  54,  53,  52,  51,  50,  63,  62,  61,  60,  59,  58,  57,
    1.64 +         70,  69,  68,  67,  66,  65,  64,  77,  76,  75,  74,  73,  72,  71,
    1.65 +         84,  83,  82,  81,  80,  79,  78,  91,  90,  89,  88,  87,  86,  85,
    1.66 +         98,  97,  96,  95,  94,  93,  92, 105, 104, 103, 102, 101, 100,  99,
    1.67 +        112, 111, 110, 109, 108, 107, 106, 119, 118, 117, 116, 115, 114, 113,
    1.68 +        126, 125, 124, 123, 122, 121, 120, 133, 132, 131, 130, 129, 128, 127,
    1.69 +        140, 139, 138, 137, 136, 135, 134, 147, 146, 145, 144, 143, 142, 141,
    1.70 +          7,   6,   5,   4,   3,   2,   1, 154, 153, 152, 151, 150, 149, 148,
    1.71 +        161, 160, 159, 158, 157, 156, 155, 168, 167, 166, 165, 164, 163, 162,
    1.72 +        175, 174, 173, 172, 171, 170, 169, 182, 181, 180, 179, 178, 177, 176,
    1.73 +        189, 188, 187, 186, 185, 184, 183, 196, 195, 194, 193, 192, 191, 190,
    1.74 +        203, 202, 201, 200, 199, 198, 197, 210, 209, 208, 207, 206, 205, 204,
    1.75 +        217, 216, 215, 214, 213, 212, 211, 294, 293, 292, 291, 290, 289, 288,
    1.76 +        301, 300, 299, 298, 297, 296, 295, 308, 307, 306, 305, 304, 303, 302,
    1.77 +        315, 314, 313, 312, 311, 310, 309, 322, 321, 320, 319, 318, 317, 316,
    1.78 +        329, 328, 327, 326, 325, 324, 323, 336, 335, 334, 333, 332, 331, 330,
    1.79 +        343, 342, 341, 340, 339, 338, 337, 350, 349, 348, 347, 346, 345, 344,
    1.80 +        357, 356, 355, 354, 353, 352, 351, 364, 363, 362, 361, 360, 359, 358,
    1.81 +        371, 370, 369, 368, 367, 366, 365, 378, 377, 376, 375, 374, 373, 372,
    1.82 +        385, 384, 383, 382, 381, 380, 379, 392, 391, 390, 389, 388, 387, 386,
    1.83 +        399, 398, 397, 396, 395, 394, 393, 406, 405, 404, 403, 402, 401, 400,
    1.84 +        413, 412, 411, 410, 409, 408, 407, 420, 419, 418, 417, 416, 415, 414,
    1.85 +        427, 426, 425, 424, 423, 422, 421, 287, 286, 285, 284, 283, 282, 281,
    1.86 +        280, 279, 278, 277, 276, 275, 274, 434, 433, 432, 431, 430, 429, 428,
    1.87 +        273, 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260,
    1.88 +        259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246,
    1.89 +        245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232,
    1.90 +        231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218,
    1.91 +        472, 471, 470, 441, 440, 439, 438, 437, 436, 435, 448, 447, 446, 445,
    1.92 +        444, 443, 442, 455, 454, 453, 452, 451, 450, 449, 462, 461, 460, 459,
    1.93 +        458, 457, 456, 469, 468, 467, 466, 465, 464, 463, 479, 478, 477, 476,
    1.94 +        475, 474, 473, 493, 492, 491, 490, 489, 488, 487, 486, 485, 484, 483,
    1.95 +        482, 481, 480, 496, 497, 495, 499, 500, 498, 494, 503, 504, 502, 506,
    1.96 +        507, 505, 501, 510, 511, 509, 513, 514, 512, 508, 517, 518, 516, 520,
    1.97 +        521, 519, 515, 524, 525, 523, 527, 528, 526, 522, 531, 532, 530, 534,
    1.98 +        535, 533, 529, 538, 539, 537, 541, 542, 540, 536, 545, 546, 544, 548,
    1.99 +        549, 547, 543, 552, 553, 551, 555, 556, 554, 550, 559, 560, 558, 562,
   1.100 +        563, 561, 557, 566, 567, 565, 569, 570, 568, 564, 573, 574, 572, 576,
   1.101 +        577, 575, 571, 580, 581, 579, 583, 584, 582, 578, 587, 588, 586, 590,
   1.102 +        591, 589, 585, 594, 595, 593, 597, 598, 596, 592, 601, 602, 600, 604,
   1.103 +        605, 603, 599, 608, 609, 607, 611, 612, 610, 606, 615, 616, 614, 618,
   1.104 +        619, 617, 613, 622, 623, 621, 625, 626, 624, 620, 629, 630, 628, 632,
   1.105 +        633, 631, 627, 640, 639, 638, 637, 636, 635, 634, 647, 646, 645, 644,
   1.106 +        643, 642, 641, 654, 653, 652, 651, 650, 649, 648, 661, 660, 659, 658,
   1.107 +        657, 656, 655, 668, 667, 666, 665, 664, 663, 662, 675, 674, 673, 672,
   1.108 +        671, 670, 669, 682, 681, 680, 679, 678, 677, 676, 689, 688, 687, 686,
   1.109 +        685, 684, 683, 696, 695, 694, 693, 692, 691, 690, 703, 702, 701, 700,
   1.110 +        699, 698, 697, 773, 772, 771, 770, 769, 768, 767, 766, 765, 764, 763,
   1.111 +        762, 761, 760, 759, 758, 757, 756, 755, 754, 753, 752, 751, 750, 749,
   1.112 +        748, 747, 746, 745, 744, 743, 742, 741, 740, 739, 738, 737, 736, 735,
   1.113 +        734, 733, 732, 731, 730, 729, 728, 727, 726, 725, 724, 723, 722, 721,
   1.114 +        720, 719, 718, 717, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707,
   1.115 +        706, 705, 704, 913, 912, 911, 910, 909, 908, 907, 906, 905, 904, 903,
   1.116 +        902, 901, 900, 899, 898, 897, 896, 895, 894, 893, 892, 891, 890, 889,
   1.117 +        888, 887, 886, 885, 884, 883, 882, 881, 880, 879, 878, 877, 876, 875,
   1.118 +        874, 873, 872, 871, 870, 869, 868, 867, 866, 865, 864, 863, 862, 861,
   1.119 +        860, 859, 858, 857, 856, 855, 854, 853, 852, 851, 850, 849, 848, 847,
   1.120 +        846, 845, 844, 843, 842, 841, 840, 839, 838, 837, 836, 835, 834, 833,
   1.121 +        832, 831, 830, 829, 828, 827, 826, 825, 824, 823, 822, 821, 820, 819,
   1.122 +        818, 817, 816, 815, 814, 813, 812, 811, 810, 809, 808, 807, 806, 805,
   1.123 +        804, 803, 802, 801, 800, 799, 798, 797, 796, 795, 794, 793, 792, 791,
   1.124 +        790, 789, 788, 787, 786, 785, 784, 783, 782, 781, 780, 779, 778, 777,
   1.125 +        776, 775, 774 };
   1.126 +
   1.127 +int32_t sAggregateTestDoOrderArr[] = {
   1.128 +          1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
   1.129 +         15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
   1.130 +         29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
   1.131 +         43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
   1.132 +         57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
   1.133 +         71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
   1.134 +         85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
   1.135 +         99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
   1.136 +        113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
   1.137 +        127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
   1.138 +        141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
   1.139 +        155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
   1.140 +        169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
   1.141 +        183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
   1.142 +        197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
   1.143 +        211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
   1.144 +        225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
   1.145 +        239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
   1.146 +        253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
   1.147 +        267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
   1.148 +        281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
   1.149 +        295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
   1.150 +        309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
   1.151 +        323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
   1.152 +        337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
   1.153 +        351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
   1.154 +        365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
   1.155 +        379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392,
   1.156 +        393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406,
   1.157 +        407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
   1.158 +        421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
   1.159 +        435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
   1.160 +        449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
   1.161 +        463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476,
   1.162 +        477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
   1.163 +        491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504,
   1.164 +        505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518,
   1.165 +        519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532,
   1.166 +        533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546,
   1.167 +        547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
   1.168 +        561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
   1.169 +        575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588,
   1.170 +        589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602,
   1.171 +        603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616,
   1.172 +        617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630,
   1.173 +        631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644,
   1.174 +        645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658,
   1.175 +        659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
   1.176 +        673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686,
   1.177 +        687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700,
   1.178 +        701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714,
   1.179 +        715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728,
   1.180 +        729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742,
   1.181 +        743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756,
   1.182 +        757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770,
   1.183 +        771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784,
   1.184 +        785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798,
   1.185 +        799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812,
   1.186 +        813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826,
   1.187 +        827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840,
   1.188 +        841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854,
   1.189 +        855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868,
   1.190 +        869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882,
   1.191 +        883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896,
   1.192 +        897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910,
   1.193 +        911, 912, 913 };
   1.194 +
   1.195 +int32_t sAggregateTestUndoOrderArr[] = {
   1.196 +        287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274,
   1.197 +        273, 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260,
   1.198 +        434, 433, 432, 431, 430, 429, 428, 273, 272, 271, 270, 269, 268, 267,
   1.199 +        266, 265, 264, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253,
   1.200 +        479, 478, 477, 476, 475, 493, 492, 491, 490, 489, 488, 487, 486, 485,
   1.201 +        484, 483, 482, 481, 480, 485, 484, 483, 482, 481, 480, 773, 772, 771,
   1.202 +        770, 769, 768, 767, 766, 765, 764, 763, 762, 761, 760, 759, 758, 757,
   1.203 +        756, 755, 754, 753, 752, 751, 750, 749, 748, 747, 746, 745, 744, 743,
   1.204 +        742, 741, 740, 739, 738, 737, 736, 735, 734, 733, 732, 731, 730, 729,
   1.205 +        728, 727, 726, 725, 724, 723, 722, 721, 720, 719, 718, 717, 716, 715,
   1.206 +        714, 713, 712, 711, 710, 709, 708, 707, 706, 705, 704, 913, 912, 911,
   1.207 +        910, 909, 908, 907, 906, 905, 904, 903, 902, 901, 900, 899, 898, 897,
   1.208 +        896, 895, 894, 893, 892, 891, 890, 889, 888, 887, 886, 885, 884, 883,
   1.209 +        882, 881, 880, 879, 878, 877, 876, 875, 874, 873, 872, 871, 870, 869,
   1.210 +        868, 867, 866, 865, 864, 863, 862, 861, 860, 859, 858, 857, 856, 855,
   1.211 +        854, 853, 852, 851, 850, 849, 848, 847, 846, 845, 844 };
   1.212 +
   1.213 +int32_t sAggregateTestRedoOrderArr[] = {
   1.214 +        260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
   1.215 +        476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486 };
   1.216 +
   1.217 +int32_t sSimpleBatchTestDestructorOrderArr[] = {
   1.218 +         21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,
   1.219 +         35,  36,  37,  38,  39,  40,  43,  42,  41,  64,  63,  62,  61,  60,
   1.220 +         59,  58,  57,  56,  55,  54,  53,  52,  51,  50,  49,  48,  47,  46,
   1.221 +         45,  44,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,  10,   9,
   1.222 +          8,   7,   6,   5,   4,   3,   2,   1,  65,  67,  66,  68,  69,  70,
   1.223 +         71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
   1.224 +         85,  86,  87, 107, 106, 105, 104, 103, 102, 101, 100,  99,  98,  97,
   1.225 +         96,  95,  94,  93,  92,  91,  90,  89,  88 };
   1.226 +
   1.227 +int32_t sSimpleBatchTestDoOrderArr[] = {
   1.228 +          1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
   1.229 +         15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
   1.230 +         29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
   1.231 +         43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
   1.232 +         57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
   1.233 +         71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
   1.234 +         85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
   1.235 +         99, 100, 101, 102, 103, 104, 105, 106, 107 };
   1.236 +
   1.237 +int32_t sSimpleBatchTestUndoOrderArr[] = {
   1.238 +         43,  42,  41,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,  10,
   1.239 +          9,   8,   7,   6,   5,   4,   3,   2,   1,  43,  42,  41,  63,  62,
   1.240 +         61,  60,  59,  58,  57,  56,  55,  54,  53,  52,  51,  50,  49,  48,
   1.241 +         47,  46,  45,  44,  65,  67,  66, 107, 106, 105, 104, 103, 102, 101,
   1.242 +        100,  99,  98 };
   1.243 +
   1.244 +int32_t sSimpleBatchTestRedoOrderArr[] = {
   1.245 +          1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
   1.246 +         15,  16,  17,  18,  19,  20,  41,  42,  43,  66 };
   1.247 +
   1.248 +int32_t sAggregateBatchTestDestructorOrderArr[] = {
   1.249 +        147, 146, 145, 144, 143, 142, 141, 154, 153, 152, 151, 150, 149, 148,
   1.250 +        161, 160, 159, 158, 157, 156, 155, 168, 167, 166, 165, 164, 163, 162,
   1.251 +        175, 174, 173, 172, 171, 170, 169, 182, 181, 180, 179, 178, 177, 176,
   1.252 +        189, 188, 187, 186, 185, 184, 183, 196, 195, 194, 193, 192, 191, 190,
   1.253 +        203, 202, 201, 200, 199, 198, 197, 210, 209, 208, 207, 206, 205, 204,
   1.254 +        217, 216, 215, 214, 213, 212, 211, 224, 223, 222, 221, 220, 219, 218,
   1.255 +        231, 230, 229, 228, 227, 226, 225, 238, 237, 236, 235, 234, 233, 232,
   1.256 +        245, 244, 243, 242, 241, 240, 239, 252, 251, 250, 249, 248, 247, 246,
   1.257 +        259, 258, 257, 256, 255, 254, 253, 266, 265, 264, 263, 262, 261, 260,
   1.258 +        273, 272, 271, 270, 269, 268, 267, 280, 279, 278, 277, 276, 275, 274,
   1.259 +        301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288,
   1.260 +        287, 286, 285, 284, 283, 282, 281, 444, 443, 442, 441, 440, 439, 438,
   1.261 +        437, 436, 435, 434, 433, 432, 431, 430, 429, 428, 427, 426, 425, 424,
   1.262 +        423, 422, 421, 420, 419, 418, 417, 416, 415, 414, 413, 412, 411, 410,
   1.263 +        409, 408, 407, 406, 405, 404, 403, 402, 401, 400, 399, 398, 397, 396,
   1.264 +        395, 394, 393, 392, 391, 390, 389, 388, 387, 386, 385, 384, 383, 382,
   1.265 +        381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 370, 369, 368,
   1.266 +        367, 366, 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, 354,
   1.267 +        353, 352, 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340,
   1.268 +        339, 338, 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326,
   1.269 +        325, 324, 323, 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, 312,
   1.270 +        311, 310, 309, 308, 307, 306, 305, 304, 303, 302, 140, 139, 138, 137,
   1.271 +        136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123,
   1.272 +        122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109,
   1.273 +        108, 107, 106, 105, 104, 103, 102, 101, 100,  99,  98,  97,  96,  95,
   1.274 +         94,  93,  92,  91,  90,  89,  88,  87,  86,  85,  84,  83,  82,  81,
   1.275 +         80,  79,  78,  77,  76,  75,  74,  73,  72,  71,  70,  69,  68,  67,
   1.276 +         66,  65,  64,  63,  62,  61,  60,  59,  58,  57,  56,  55,  54,  53,
   1.277 +         52,  51,  50,  49,  48,  47,  46,  45,  44,  43,  42,  41,  40,  39,
   1.278 +         38,  37,  36,  35,  34,  33,  32,  31,  30,  29,  28,  27,  26,  25,
   1.279 +         24,  23,  22,  21,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,
   1.280 +         10,   9,   8,   7,   6,   5,   4,   3,   2,   1, 451, 450, 449, 448,
   1.281 +        447, 446, 445, 465, 464, 463, 462, 461, 460, 459, 458, 457, 456, 455,
   1.282 +        454, 453, 452, 468, 469, 467, 471, 472, 470, 466, 475, 476, 474, 478,
   1.283 +        479, 477, 473, 482, 483, 481, 485, 486, 484, 480, 489, 490, 488, 492,
   1.284 +        493, 491, 487, 496, 497, 495, 499, 500, 498, 494, 503, 504, 502, 506,
   1.285 +        507, 505, 501, 510, 511, 509, 513, 514, 512, 508, 517, 518, 516, 520,
   1.286 +        521, 519, 515, 524, 525, 523, 527, 528, 526, 522, 531, 532, 530, 534,
   1.287 +        535, 533, 529, 538, 539, 537, 541, 542, 540, 536, 545, 546, 544, 548,
   1.288 +        549, 547, 543, 552, 553, 551, 555, 556, 554, 550, 559, 560, 558, 562,
   1.289 +        563, 561, 557, 566, 567, 565, 569, 570, 568, 564, 573, 574, 572, 576,
   1.290 +        577, 575, 571, 580, 581, 579, 583, 584, 582, 578, 587, 588, 586, 590,
   1.291 +        591, 589, 585, 594, 595, 593, 597, 598, 596, 592, 601, 602, 600, 604,
   1.292 +        605, 603, 599, 745, 744, 743, 742, 741, 740, 739, 738, 737, 736, 735,
   1.293 +        734, 733, 732, 731, 730, 729, 728, 727, 726, 725, 724, 723, 722, 721,
   1.294 +        720, 719, 718, 717, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707,
   1.295 +        706, 705, 704, 703, 702, 701, 700, 699, 698, 697, 696, 695, 694, 693,
   1.296 +        692, 691, 690, 689, 688, 687, 686, 685, 684, 683, 682, 681, 680, 679,
   1.297 +        678, 677, 676, 675, 674, 673, 672, 671, 670, 669, 668, 667, 666, 665,
   1.298 +        664, 663, 662, 661, 660, 659, 658, 657, 656, 655, 654, 653, 652, 651,
   1.299 +        650, 649, 648, 647, 646, 645, 644, 643, 642, 641, 640, 639, 638, 637,
   1.300 +        636, 635, 634, 633, 632, 631, 630, 629, 628, 627, 626, 625, 624, 623,
   1.301 +        622, 621, 620, 619, 618, 617, 616, 615, 614, 613, 612, 611, 610, 609,
   1.302 +        608, 607, 606 };
   1.303 +
   1.304 +int32_t sAggregateBatchTestDoOrderArr[] = {
   1.305 +          1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
   1.306 +         15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
   1.307 +         29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
   1.308 +         43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
   1.309 +         57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
   1.310 +         71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
   1.311 +         85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
   1.312 +         99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
   1.313 +        113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
   1.314 +        127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
   1.315 +        141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
   1.316 +        155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
   1.317 +        169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
   1.318 +        183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
   1.319 +        197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
   1.320 +        211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
   1.321 +        225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
   1.322 +        239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
   1.323 +        253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
   1.324 +        267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
   1.325 +        281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
   1.326 +        295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
   1.327 +        309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
   1.328 +        323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
   1.329 +        337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
   1.330 +        351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
   1.331 +        365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
   1.332 +        379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392,
   1.333 +        393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406,
   1.334 +        407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
   1.335 +        421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
   1.336 +        435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
   1.337 +        449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
   1.338 +        463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476,
   1.339 +        477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
   1.340 +        491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504,
   1.341 +        505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518,
   1.342 +        519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532,
   1.343 +        533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546,
   1.344 +        547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
   1.345 +        561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
   1.346 +        575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588,
   1.347 +        589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602,
   1.348 +        603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616,
   1.349 +        617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630,
   1.350 +        631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644,
   1.351 +        645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658,
   1.352 +        659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
   1.353 +        673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686,
   1.354 +        687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700,
   1.355 +        701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714,
   1.356 +        715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728,
   1.357 +        729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742,
   1.358 +        743, 744, 745 };
   1.359 +
   1.360 +int32_t sAggregateBatchTestUndoOrderArr[] = {
   1.361 +        301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288,
   1.362 +        287, 286, 285, 284, 283, 282, 281, 140, 139, 138, 137, 136, 135, 134,
   1.363 +        133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120,
   1.364 +        119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106,
   1.365 +        105, 104, 103, 102, 101, 100,  99,  98,  97,  96,  95,  94,  93,  92,
   1.366 +         91,  90,  89,  88,  87,  86,  85,  84,  83,  82,  81,  80,  79,  78,
   1.367 +         77,  76,  75,  74,  73,  72,  71,  70,  69,  68,  67,  66,  65,  64,
   1.368 +         63,  62,  61,  60,  59,  58,  57,  56,  55,  54,  53,  52,  51,  50,
   1.369 +         49,  48,  47,  46,  45,  44,  43,  42,  41,  40,  39,  38,  37,  36,
   1.370 +         35,  34,  33,  32,  31,  30,  29,  28,  27,  26,  25,  24,  23,  22,
   1.371 +         21,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,  10,   9,   8,
   1.372 +          7,   6,   5,   4,   3,   2,   1, 301, 300, 299, 298, 297, 296, 295,
   1.373 +        294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281,
   1.374 +        441, 440, 439, 438, 437, 436, 435, 434, 433, 432, 431, 430, 429, 428,
   1.375 +        427, 426, 425, 424, 423, 422, 421, 420, 419, 418, 417, 416, 415, 414,
   1.376 +        413, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, 400,
   1.377 +        399, 398, 397, 396, 395, 394, 393, 392, 391, 390, 389, 388, 387, 386,
   1.378 +        385, 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372,
   1.379 +        371, 370, 369, 368, 367, 366, 365, 364, 363, 362, 361, 360, 359, 358,
   1.380 +        357, 356, 355, 354, 353, 352, 351, 350, 349, 348, 347, 346, 345, 344,
   1.381 +        343, 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, 331, 330,
   1.382 +        329, 328, 327, 326, 325, 324, 323, 322, 321, 320, 319, 318, 317, 316,
   1.383 +        315, 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, 304, 303, 302,
   1.384 +        451, 450, 449, 448, 447, 465, 464, 463, 462, 461, 460, 459, 458, 457,
   1.385 +        456, 455, 454, 453, 452, 457, 456, 455, 454, 453, 452, 745, 744, 743,
   1.386 +        742, 741, 740, 739, 738, 737, 736, 735, 734, 733, 732, 731, 730, 729,
   1.387 +        728, 727, 726, 725, 724, 723, 722, 721, 720, 719, 718, 717, 716, 715,
   1.388 +        714, 713, 712, 711, 710, 709, 708, 707, 706, 705, 704, 703, 702, 701,
   1.389 +        700, 699, 698, 697, 696, 695, 694, 693, 692, 691, 690, 689, 688, 687,
   1.390 +        686, 685, 684, 683, 682, 681, 680, 679, 678, 677, 676 };
   1.391 +
   1.392 +int32_t sAggregateBatchTestRedoOrderArr[] = {
   1.393 +          1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
   1.394 +         15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
   1.395 +         29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
   1.396 +         43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
   1.397 +         57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
   1.398 +         71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
   1.399 +         85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
   1.400 +         99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
   1.401 +        113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
   1.402 +        127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
   1.403 +        281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
   1.404 +        295, 296, 297, 298, 299, 300, 301, 448, 449, 450, 451, 452, 453, 454,
   1.405 +        455, 456, 457, 458 };
   1.406 +
   1.407 +#define TEST_TXMGR_IF_RELEASE(tx) if (tx) tx->Release(); // Release but don't clear pointer!
   1.408 +
   1.409 +class TestTransaction : public nsITransaction
   1.410 +{
   1.411 +public:
   1.412 +
   1.413 +  TestTransaction() {}
   1.414 +  virtual ~TestTransaction() {}
   1.415 +
   1.416 +  NS_DECL_ISUPPORTS
   1.417 +};
   1.418 +
   1.419 +NS_IMPL_ISUPPORTS(TestTransaction, nsITransaction)
   1.420 +
   1.421 +class SimpleTransaction : public TestTransaction
   1.422 +{
   1.423 +protected:
   1.424 +
   1.425 +#define NONE_FLAG               0
   1.426 +#define THROWS_DO_ERROR_FLAG    1
   1.427 +#define THROWS_UNDO_ERROR_FLAG  2
   1.428 +#define THROWS_REDO_ERROR_FLAG  4
   1.429 +#define MERGE_FLAG              8
   1.430 +#define TRANSIENT_FLAG         16
   1.431 +#define BATCH_FLAG             32
   1.432 +#define ALL_ERROR_FLAGS        (THROWS_DO_ERROR_FLAG|THROWS_UNDO_ERROR_FLAG|THROWS_REDO_ERROR_FLAG)
   1.433 +
   1.434 +  int32_t mVal;
   1.435 +  int32_t mFlags;
   1.436 +
   1.437 +public:
   1.438 +
   1.439 +  SimpleTransaction(int32_t aFlags=NONE_FLAG)
   1.440 +                    : mVal(++sConstructorCount), mFlags(aFlags)
   1.441 +  {}
   1.442 +
   1.443 +  virtual ~SimpleTransaction()
   1.444 +  {
   1.445 +    //
   1.446 +    // Make sure transactions are being destroyed in the order we expect!
   1.447 +    // Notice that we don't check to see if we go past the end of the array.
   1.448 +    // This is done on purpose since we want to crash if the order array is out
   1.449 +    // of date.
   1.450 +    //
   1.451 +    /* Disabled because the current cycle collector doesn't delete
   1.452 +       cycle collectable objects synchronously, nor doesn't guarantee any order.
   1.453 +    if (sDestructorOrderArr && mVal != sDestructorOrderArr[sDestructorCount]) {
   1.454 +      fail("~SimpleTransaction expected %d got %d.\n",
   1.455 +           mVal, sDestructorOrderArr[sDestructorCount]);
   1.456 +      exit(-1);
   1.457 +    }
   1.458 +    */
   1.459 +
   1.460 +    ++sDestructorCount;
   1.461 +
   1.462 +#ifdef ENABLE_DEBUG_PRINTFS
   1.463 +    printf("\n~SimpleTransaction: %d - 0x%.8x\n", mVal, (int32_t)this);
   1.464 +#endif // ENABLE_DEBUG_PRINTFS
   1.465 +
   1.466 +    mVal = -1;
   1.467 +  }
   1.468 +
   1.469 +  NS_IMETHOD DoTransaction()
   1.470 +  {
   1.471 +    //
   1.472 +    // Make sure DoTransaction() is called in the order we expect!
   1.473 +    // Notice that we don't check to see if we go past the end of the array.
   1.474 +    // This is done on purpose since we want to crash if the order array is out
   1.475 +    // of date.
   1.476 +    //
   1.477 +    if (sDoOrderArr && mVal != sDoOrderArr[sDoCount]) {
   1.478 +      fail("DoTransaction expected %d got %d.\n",
   1.479 +           mVal, sDoOrderArr[sDoCount]);
   1.480 +      exit(-1);
   1.481 +    }
   1.482 +
   1.483 +    ++sDoCount;
   1.484 +
   1.485 +#ifdef ENABLE_DEBUG_PRINTFS
   1.486 +    printf("\nSimpleTransaction.DoTransaction: %d - 0x%.8x\n", mVal, (int32_t)this);
   1.487 +#endif // ENABLE_DEBUG_PRINTFS
   1.488 +
   1.489 +    return (mFlags & THROWS_DO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
   1.490 +  }
   1.491 +
   1.492 +  NS_IMETHOD UndoTransaction()
   1.493 +  {
   1.494 +    //
   1.495 +    // Make sure UndoTransaction() is called in the order we expect!
   1.496 +    // Notice that we don't check to see if we go past the end of the array.
   1.497 +    // This is done on purpose since we want to crash if the order array is out
   1.498 +    // of date.
   1.499 +    //
   1.500 +    if (sUndoOrderArr && mVal != sUndoOrderArr[sUndoCount]) {
   1.501 +      fail("UndoTransaction expected %d got %d.\n",
   1.502 +           mVal, sUndoOrderArr[sUndoCount]);
   1.503 +      exit(-1);
   1.504 +    }
   1.505 +
   1.506 +    ++sUndoCount;
   1.507 +
   1.508 +#ifdef ENABLE_DEBUG_PRINTFS
   1.509 +    printf("\nSimpleTransaction.Undo: %d - 0x%.8x\n", mVal, (int32_t)this);
   1.510 +#endif // ENABLE_DEBUG_PRINTFS
   1.511 +
   1.512 +    return (mFlags & THROWS_UNDO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
   1.513 +  }
   1.514 +
   1.515 +  NS_IMETHOD RedoTransaction()
   1.516 +  {
   1.517 +    //
   1.518 +    // Make sure RedoTransaction() is called in the order we expect!
   1.519 +    // Notice that we don't check to see if we go past the end of the array.
   1.520 +    // This is done on purpose since we want to crash if the order array is out
   1.521 +    // of date.
   1.522 +    //
   1.523 +    if (sRedoOrderArr && mVal != sRedoOrderArr[sRedoCount]) {
   1.524 +      fail("RedoTransaction expected %d got %d.\n",
   1.525 +           mVal, sRedoOrderArr[sRedoCount]);
   1.526 +      exit(-1);
   1.527 +    }
   1.528 +
   1.529 +    ++sRedoCount;
   1.530 +
   1.531 +#ifdef ENABLE_DEBUG_PRINTFS
   1.532 +    printf("\nSimpleTransaction.Redo: %d - 0x%.8x\n", mVal, (int32_t)this);
   1.533 +#endif // ENABLE_DEBUG_PRINTFS
   1.534 +
   1.535 +    return (mFlags & THROWS_REDO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
   1.536 +  }
   1.537 +
   1.538 +  NS_IMETHOD GetIsTransient(bool *aIsTransient)
   1.539 +  {
   1.540 +    if (aIsTransient)
   1.541 +      *aIsTransient = (mFlags & TRANSIENT_FLAG) ? true : false;
   1.542 +
   1.543 +    return NS_OK;
   1.544 +  }
   1.545 +
   1.546 +  NS_IMETHOD Merge(nsITransaction *aTransaction, bool *aDidMerge)
   1.547 +  {
   1.548 +    if (aDidMerge)
   1.549 +      *aDidMerge = (mFlags & MERGE_FLAG) ? true : false;
   1.550 +
   1.551 +    return NS_OK;
   1.552 +  }
   1.553 +};
   1.554 +
   1.555 +class AggregateTransaction : public SimpleTransaction
   1.556 +{
   1.557 +private:
   1.558 +
   1.559 +  AggregateTransaction(nsITransactionManager *aTXMgr, int32_t aLevel,
   1.560 +                       int32_t aNumber, int32_t aMaxLevel,
   1.561 +                       int32_t aNumChildrenPerNode,
   1.562 +                       int32_t aFlags)
   1.563 +  {
   1.564 +    mLevel              = aLevel;
   1.565 +    mNumber             = aNumber;
   1.566 +    mTXMgr              = aTXMgr;
   1.567 +    mFlags              = aFlags & (~ALL_ERROR_FLAGS);
   1.568 +    mErrorFlags         = aFlags & ALL_ERROR_FLAGS;
   1.569 +    mTXMgr              = aTXMgr;
   1.570 +    mMaxLevel           = aMaxLevel;
   1.571 +    mNumChildrenPerNode = aNumChildrenPerNode;
   1.572 +  }
   1.573 +
   1.574 +  nsITransactionManager *mTXMgr;
   1.575 +
   1.576 +  int32_t mLevel;
   1.577 +  int32_t mNumber;
   1.578 +  int32_t mErrorFlags;
   1.579 +
   1.580 +  int32_t mMaxLevel;
   1.581 +  int32_t mNumChildrenPerNode;
   1.582 +
   1.583 +public:
   1.584 +
   1.585 +  AggregateTransaction(nsITransactionManager *aTXMgr,
   1.586 +                       int32_t aMaxLevel, int32_t aNumChildrenPerNode,
   1.587 +                       int32_t aFlags=NONE_FLAG)
   1.588 +  {
   1.589 +    mLevel              = 1;
   1.590 +    mNumber             = 1;
   1.591 +    mFlags              = aFlags & (~ALL_ERROR_FLAGS);
   1.592 +    mErrorFlags         = aFlags & ALL_ERROR_FLAGS;
   1.593 +    mTXMgr              = aTXMgr;
   1.594 +    mMaxLevel           = aMaxLevel;
   1.595 +    mNumChildrenPerNode = aNumChildrenPerNode;
   1.596 +  }
   1.597 +
   1.598 +  virtual ~AggregateTransaction()
   1.599 +  {
   1.600 +    // printf("~AggregateTransaction(0x%.8x) - %3d (%3d)\n", this, mLevel, mVal);
   1.601 +  }
   1.602 +
   1.603 +  NS_IMETHOD DoTransaction()
   1.604 +  {
   1.605 +    if (mLevel >= mMaxLevel) {
   1.606 +      // Only leaf nodes can throw errors!
   1.607 +      mFlags |= mErrorFlags;
   1.608 +    }
   1.609 +
   1.610 +    nsresult result = SimpleTransaction::DoTransaction();
   1.611 +
   1.612 +    if (NS_FAILED(result)) {
   1.613 +      // fail("QueryInterface() failed for transaction level %d. (%d)\n",
   1.614 +      //      mLevel, result);
   1.615 +      return result;
   1.616 +    }
   1.617 +
   1.618 +    if (mLevel >= mMaxLevel)
   1.619 +      return NS_OK;
   1.620 +
   1.621 +    if (mFlags & BATCH_FLAG) {
   1.622 +      result = mTXMgr->BeginBatch(nullptr);
   1.623 +      if (NS_FAILED(result)) {
   1.624 +        return result;
   1.625 +      }
   1.626 +    }
   1.627 +
   1.628 +    int32_t cLevel = mLevel + 1;
   1.629 +
   1.630 +    for (int i = 1; i <= mNumChildrenPerNode; i++) {
   1.631 +      int32_t flags = mErrorFlags & THROWS_DO_ERROR_FLAG;
   1.632 +
   1.633 +      if ((mErrorFlags & THROWS_REDO_ERROR_FLAG) && i == mNumChildrenPerNode) {
   1.634 +        // Make the rightmost leaf transaction throw the error!
   1.635 +        flags = THROWS_REDO_ERROR_FLAG;
   1.636 +        mErrorFlags = mErrorFlags & (~THROWS_REDO_ERROR_FLAG);
   1.637 +      }
   1.638 +      else if ((mErrorFlags & THROWS_UNDO_ERROR_FLAG)
   1.639 +               && i == 1) {
   1.640 +        // Make the leftmost leaf transaction throw the error!
   1.641 +        flags = THROWS_UNDO_ERROR_FLAG;
   1.642 +        mErrorFlags = mErrorFlags & (~THROWS_UNDO_ERROR_FLAG);
   1.643 +      }
   1.644 +
   1.645 +      flags |= mFlags & BATCH_FLAG;
   1.646 +
   1.647 +      AggregateTransaction *tximpl =
   1.648 +              new AggregateTransaction(mTXMgr, cLevel, i, mMaxLevel,
   1.649 +                                       mNumChildrenPerNode, flags);
   1.650 +
   1.651 +      if (!tximpl) {
   1.652 +        fail("Failed to allocate AggregateTransaction %d, level %d. (%d)\n",
   1.653 +             i, mLevel, result);
   1.654 +
   1.655 +        if (mFlags & BATCH_FLAG)
   1.656 +          mTXMgr->EndBatch(false);
   1.657 +
   1.658 +        return NS_ERROR_OUT_OF_MEMORY;
   1.659 +      }
   1.660 +
   1.661 +      nsITransaction *tx = 0;
   1.662 +      result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
   1.663 +      if (NS_FAILED(result)) {
   1.664 +        fail("QueryInterface() failed for transaction %d, level %d. (%d)\n",
   1.665 +             i, mLevel, result);
   1.666 +
   1.667 +        if (mFlags & BATCH_FLAG)
   1.668 +          mTXMgr->EndBatch(false);
   1.669 +
   1.670 +        return result;
   1.671 +      }
   1.672 +
   1.673 +      result = mTXMgr->DoTransaction(tx);
   1.674 +
   1.675 +      if (NS_FAILED(result)) {
   1.676 +        // fail("Failed to execute transaction %d, level %d. (%d)\n",
   1.677 +        //      i, mLevel, result);
   1.678 +        tx->Release();
   1.679 +
   1.680 +        if (mFlags & BATCH_FLAG)
   1.681 +          mTXMgr->EndBatch(false);
   1.682 +
   1.683 +        return result;
   1.684 +      }
   1.685 +
   1.686 +      tx->Release();
   1.687 +    }
   1.688 +
   1.689 +    if (mFlags & BATCH_FLAG)
   1.690 +      mTXMgr->EndBatch(false);
   1.691 +
   1.692 +    return result;
   1.693 +  }
   1.694 +};
   1.695 +
   1.696 +class TestTransactionFactory
   1.697 +{
   1.698 +public:
   1.699 +  virtual TestTransaction *create(nsITransactionManager *txmgr, int32_t flags) = 0;
   1.700 +};
   1.701 +
   1.702 +class SimpleTransactionFactory : public TestTransactionFactory
   1.703 +{
   1.704 +public:
   1.705 +
   1.706 +  TestTransaction *create(nsITransactionManager *txmgr, int32_t flags)
   1.707 +  {
   1.708 +    return (TestTransaction *)new SimpleTransaction(flags);
   1.709 +  }
   1.710 +};
   1.711 +
   1.712 +class AggregateTransactionFactory : public TestTransactionFactory
   1.713 +{
   1.714 +private:
   1.715 +
   1.716 +  int32_t mMaxLevel;
   1.717 +  int32_t mNumChildrenPerNode;
   1.718 +  int32_t mFixedFlags;
   1.719 +
   1.720 +public:
   1.721 +
   1.722 +  AggregateTransactionFactory(int32_t aMaxLevel, int32_t aNumChildrenPerNode,
   1.723 +                              int32_t aFixedFlags=NONE_FLAG)
   1.724 +      : mMaxLevel(aMaxLevel), mNumChildrenPerNode(aNumChildrenPerNode),
   1.725 +        mFixedFlags(aFixedFlags)
   1.726 +  {
   1.727 +  }
   1.728 +
   1.729 +  virtual TestTransaction *create(nsITransactionManager *txmgr, int32_t flags)
   1.730 +  {
   1.731 +    return (TestTransaction *)new AggregateTransaction(txmgr, mMaxLevel,
   1.732 +                                                       mNumChildrenPerNode,
   1.733 +                                                       flags | mFixedFlags);
   1.734 +  }
   1.735 +};
   1.736 +
   1.737 +void
   1.738 +reset_globals()
   1.739 +{
   1.740 +  sConstructorCount   = 0;
   1.741 +
   1.742 +  sDestructorCount    = 0;
   1.743 +  sDestructorOrderArr = 0;
   1.744 +
   1.745 +  sDoCount            = 0;
   1.746 +  sDoOrderArr         = 0;
   1.747 +
   1.748 +  sUndoCount          = 0;
   1.749 +  sUndoOrderArr       = 0;
   1.750 +
   1.751 +  sRedoCount          = 0;
   1.752 +  sRedoOrderArr       = 0;
   1.753 +}
   1.754 +
   1.755 +/**
   1.756 + * Test behaviors in non-batch mode.
   1.757 + **/
   1.758 +nsresult
   1.759 +quick_test(TestTransactionFactory *factory)
   1.760 +{
   1.761 +  nsresult result;
   1.762 +
   1.763 +  /*******************************************************************
   1.764 +   *
   1.765 +   * Create a transaction manager implementation:
   1.766 +   *
   1.767 +   *******************************************************************/
   1.768 +
   1.769 +  nsCOMPtr<nsITransactionManager> mgr =
   1.770 +    do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
   1.771 +  if (NS_FAILED(result) || !mgr) {
   1.772 +    fail("Failed to create Transaction Manager instance.\n");
   1.773 +    return NS_ERROR_OUT_OF_MEMORY;
   1.774 +  }
   1.775 +
   1.776 +  passed("Create transaction manager instance");
   1.777 +
   1.778 +  /*******************************************************************
   1.779 +   *
   1.780 +   * Call DoTransaction() with a null transaction:
   1.781 +   *
   1.782 +   *******************************************************************/
   1.783 +
   1.784 +  result = mgr->DoTransaction(0);
   1.785 +
   1.786 +  if (result != NS_ERROR_NULL_POINTER) {
   1.787 +    fail("DoTransaction() returned unexpected error. (%d)\n", result);
   1.788 +    return result;
   1.789 +  }
   1.790 +
   1.791 +  passed("Call DoTransaction() with null transaction");
   1.792 +
   1.793 +  /*******************************************************************
   1.794 +   *
   1.795 +   * Call UndoTransaction() with an empty undo stack:
   1.796 +   *
   1.797 +   *******************************************************************/
   1.798 +
   1.799 +  result = mgr->UndoTransaction();
   1.800 +
   1.801 +  if (NS_FAILED(result)) {
   1.802 +    fail("Undo on empty undo stack failed. (%d)\n", result);
   1.803 +    return result;
   1.804 +  }
   1.805 +
   1.806 +  passed("Call UndoTransaction() with empty undo stack");
   1.807 +
   1.808 +  /*******************************************************************
   1.809 +   *
   1.810 +   * Call RedoTransaction() with an empty redo stack:
   1.811 +   *
   1.812 +   *******************************************************************/
   1.813 +
   1.814 +  result = mgr->RedoTransaction();
   1.815 +
   1.816 +  if (NS_FAILED(result)) {
   1.817 +    fail("Redo on empty redo stack failed. (%d)\n", result);
   1.818 +    return result;
   1.819 +  }
   1.820 +
   1.821 +  passed("Call RedoTransaction() with empty redo stack");
   1.822 +
   1.823 +  /*******************************************************************
   1.824 +   *
   1.825 +   * Call SetMaxTransactionCount(-1) with empty undo and redo stacks:
   1.826 +   *
   1.827 +   *******************************************************************/
   1.828 +
   1.829 +  result = mgr->SetMaxTransactionCount(-1);
   1.830 +
   1.831 +  if (NS_FAILED(result)) {
   1.832 +    fail("SetMaxTransactionCount(-1) failed. (%d)\n", result);
   1.833 +    return result;
   1.834 +  }
   1.835 +
   1.836 +  passed("Call SetMaxTransactionCount(-1) with empty undo and redo stacks");
   1.837 +
   1.838 +  /*******************************************************************
   1.839 +   *
   1.840 +   * Call SetMaxTransactionCount(0) with empty undo and redo stacks:
   1.841 +   *
   1.842 +   *******************************************************************/
   1.843 +
   1.844 +  result = mgr->SetMaxTransactionCount(0);
   1.845 +
   1.846 +  if (NS_FAILED(result)) {
   1.847 +    fail("SetMaxTransactionCount(0) failed. (%d)\n", result);
   1.848 +    return result;
   1.849 +  }
   1.850 +
   1.851 +  passed("Call SetMaxTransactionCount(0) with empty undo and redo stacks");
   1.852 +
   1.853 +  /*******************************************************************
   1.854 +   *
   1.855 +   * Call SetMaxTransactionCount(10) with empty undo and redo stacks:
   1.856 +   *
   1.857 +   *******************************************************************/
   1.858 +
   1.859 +  result = mgr->SetMaxTransactionCount(10);
   1.860 +
   1.861 +  if (NS_FAILED(result)) {
   1.862 +    fail("SetMaxTransactionCount(10) failed. (%d)\n", result);
   1.863 +    return result;
   1.864 +  }
   1.865 +
   1.866 +  passed("Call SetMaxTransactionCount(10) with empty undo and redo stacks");
   1.867 +
   1.868 +  /*******************************************************************
   1.869 +   *
   1.870 +   * Call Clear() with empty undo and redo stacks:
   1.871 +   *
   1.872 +   *******************************************************************/
   1.873 +
   1.874 +  result = mgr->Clear();
   1.875 +  if (NS_FAILED(result)) {
   1.876 +    fail("Clear on empty undo and redo stack failed. (%d)\n", result);
   1.877 +    return result;
   1.878 +  }
   1.879 +
   1.880 +  passed("Call Clear() with empty undo and redo stack");
   1.881 +
   1.882 +  int32_t numitems;
   1.883 +
   1.884 +  /*******************************************************************
   1.885 +   *
   1.886 +   * Call GetNumberOfUndoItems() with an empty undo stack:
   1.887 +   *
   1.888 +   *******************************************************************/
   1.889 +
   1.890 +  result = mgr->GetNumberOfUndoItems(&numitems);
   1.891 +
   1.892 +  if (NS_FAILED(result)) {
   1.893 +    fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
   1.894 +         result);
   1.895 +    return result;
   1.896 +  }
   1.897 +
   1.898 +  if (numitems != 0) {
   1.899 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
   1.900 +         numitems, result);
   1.901 +    return NS_ERROR_FAILURE;
   1.902 +  }
   1.903 +
   1.904 +  passed("Call GetNumberOfUndoItems() with empty undo stack");
   1.905 +
   1.906 +  /*******************************************************************
   1.907 +   *
   1.908 +   * Call GetNumberOfRedoItems() with an empty redo stack:
   1.909 +   *
   1.910 +   *******************************************************************/
   1.911 +
   1.912 +  result = mgr->GetNumberOfRedoItems(&numitems);
   1.913 +
   1.914 +  if (NS_FAILED(result)) {
   1.915 +    fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
   1.916 +         result);
   1.917 +    return result;
   1.918 +  }
   1.919 +
   1.920 +  if (numitems != 0) {
   1.921 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
   1.922 +         numitems, result);
   1.923 +    return NS_ERROR_FAILURE;
   1.924 +  }
   1.925 +
   1.926 +  passed("Call GetNumberOfRedoItems() with empty redo stack");
   1.927 +
   1.928 +  nsITransaction *tx;
   1.929 +
   1.930 +  /*******************************************************************
   1.931 +   *
   1.932 +   * Call PeekUndoStack() with an empty undo stack:
   1.933 +   *
   1.934 +   *******************************************************************/
   1.935 +
   1.936 +  tx = 0;
   1.937 +  result = mgr->PeekUndoStack(&tx);
   1.938 +
   1.939 +  TEST_TXMGR_IF_RELEASE(tx); // Don't hold onto any references!
   1.940 +
   1.941 +  if (NS_FAILED(result)) {
   1.942 +    fail("PeekUndoStack() on empty undo stack failed. (%d)\n", result);
   1.943 +    return result;
   1.944 +  }
   1.945 +
   1.946 +  if (tx != 0) {
   1.947 +    fail("PeekUndoStack() on empty undo stack failed. (%d)\n", result);
   1.948 +    return NS_ERROR_FAILURE;
   1.949 +  }
   1.950 +
   1.951 +  passed("Call PeekUndoStack() with empty undo stack");
   1.952 +
   1.953 +  /*******************************************************************
   1.954 +   *
   1.955 +   * Call PeekRedoStack() with an empty undo stack:
   1.956 +   *
   1.957 +   *******************************************************************/
   1.958 +
   1.959 +  tx = 0;
   1.960 +  result = mgr->PeekRedoStack(&tx);
   1.961 +
   1.962 +  TEST_TXMGR_IF_RELEASE(tx); // Don't hold onto any references!
   1.963 +
   1.964 +  if (NS_FAILED(result)) {
   1.965 +    fail("PeekRedoStack() on empty redo stack failed. (%d)\n", result);
   1.966 +    return result;
   1.967 +  }
   1.968 +
   1.969 +  if (tx != 0) {
   1.970 +    fail("PeekRedoStack() on empty redo stack failed. (%d)\n", result);
   1.971 +    return NS_ERROR_FAILURE;
   1.972 +  }
   1.973 +
   1.974 +  passed("Call PeekRedoStack() with empty undo stack");
   1.975 +
   1.976 +  /*******************************************************************
   1.977 +   *
   1.978 +   * Call AddListener() with a null listener pointer:
   1.979 +   *
   1.980 +   *******************************************************************/
   1.981 +
   1.982 +  result = mgr->AddListener(0);
   1.983 +
   1.984 +  if (result != NS_ERROR_NULL_POINTER) {
   1.985 +    fail("AddListener() returned unexpected error. (%d)\n", result);
   1.986 +    return result;
   1.987 +  }
   1.988 +
   1.989 +  passed("Call AddListener() with null listener");
   1.990 +
   1.991 +  /*******************************************************************
   1.992 +   *
   1.993 +   * Call RemoveListener() with a null listener pointer:
   1.994 +   *
   1.995 +   *******************************************************************/
   1.996 +
   1.997 +  result = mgr->RemoveListener(0);
   1.998 +
   1.999 +  if (result != NS_ERROR_NULL_POINTER) {
  1.1000 +    fail("RemoveListener() returned unexpected error. (%d)\n", result);
  1.1001 +    return result;
  1.1002 +  }
  1.1003 +
  1.1004 +  passed("Call RemoveListener() with null listener");
  1.1005 +
  1.1006 +  int32_t i;
  1.1007 +  TestTransaction *tximpl;
  1.1008 +  nsITransaction *u1, *u2;
  1.1009 +  nsITransaction *r1, *r2;
  1.1010 +
  1.1011 +  /*******************************************************************
  1.1012 +   *
  1.1013 +   * Test coalescing by executing a transaction that can merge any
  1.1014 +   * command into itself. Then execute 20 transaction. Afterwards,
  1.1015 +   * we should still have the first transaction sitting on the undo
  1.1016 +   * stack. Then clear the undo and redo stacks.
  1.1017 +   *
  1.1018 +   *******************************************************************/
  1.1019 +
  1.1020 +  result = mgr->SetMaxTransactionCount(10);
  1.1021 +
  1.1022 +  if (NS_FAILED(result)) {
  1.1023 +    fail("SetMaxTransactionCount(10) failed. (%d)\n", result);
  1.1024 +    return result;
  1.1025 +  }
  1.1026 +
  1.1027 +
  1.1028 +  tximpl = factory->create(mgr, MERGE_FLAG);
  1.1029 +
  1.1030 +  if (!tximpl) {
  1.1031 +    fail("Failed to allocate initial transaction.\n");
  1.1032 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1033 +  }
  1.1034 +
  1.1035 +  tx = 0;
  1.1036 +
  1.1037 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.1038 +
  1.1039 +  if (NS_FAILED(result)) {
  1.1040 +    fail("QueryInterface() failed for initial transaction. (%d)\n",
  1.1041 +         result);
  1.1042 +    return result;
  1.1043 +  }
  1.1044 +
  1.1045 +  result = mgr->DoTransaction(tx);
  1.1046 +
  1.1047 +  if (NS_FAILED(result)) {
  1.1048 +    fail("Failed to execute initial transaction. (%d)\n", result);
  1.1049 +    return result;
  1.1050 +  }
  1.1051 +
  1.1052 +  tx->Release();
  1.1053 +
  1.1054 +  u1 = u2 = r1 = r2 = 0;
  1.1055 +
  1.1056 +  result = mgr->PeekUndoStack(&u1);
  1.1057 +
  1.1058 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.1059 +
  1.1060 +  if (NS_FAILED(result)) {
  1.1061 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.1062 +    return result;
  1.1063 +  }
  1.1064 +
  1.1065 +  if (u1 != tx) {
  1.1066 +    fail("Top of undo stack is different!. (%d)\n", result);
  1.1067 +    return NS_ERROR_FAILURE;
  1.1068 +  }
  1.1069 +
  1.1070 +  result = mgr->PeekRedoStack(&r1);
  1.1071 +
  1.1072 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.1073 +
  1.1074 +  if (NS_FAILED(result)) {
  1.1075 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.1076 +    return result;
  1.1077 +  }
  1.1078 +
  1.1079 +  for (i = 1; i <= 20; i++) {
  1.1080 +    tximpl = factory->create(mgr, NONE_FLAG);
  1.1081 +
  1.1082 +    if (!tximpl) {
  1.1083 +      fail("Failed to allocate transaction %d.\n", i);
  1.1084 +      return NS_ERROR_OUT_OF_MEMORY;
  1.1085 +    }
  1.1086 +
  1.1087 +    tx = 0;
  1.1088 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.1089 +    if (NS_FAILED(result)) {
  1.1090 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.1091 +           i, result);
  1.1092 +      return result;
  1.1093 +    }
  1.1094 +
  1.1095 +    result = mgr->DoTransaction(tx);
  1.1096 +    if (NS_FAILED(result)) {
  1.1097 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.1098 +      return result;
  1.1099 +    }
  1.1100 +
  1.1101 +    tx->Release();
  1.1102 +  }
  1.1103 +
  1.1104 +  result = mgr->PeekUndoStack(&u2);
  1.1105 +
  1.1106 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.1107 +
  1.1108 +  if (NS_FAILED(result)) {
  1.1109 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.1110 +    return result;
  1.1111 +  }
  1.1112 +
  1.1113 +  if (u1 != u2) {
  1.1114 +    fail("Top of undo stack changed. (%d)\n", result);
  1.1115 +    return NS_ERROR_FAILURE;
  1.1116 +  }
  1.1117 +
  1.1118 +  result = mgr->PeekRedoStack(&r2);
  1.1119 +
  1.1120 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.1121 +
  1.1122 +  if (NS_FAILED(result)) {
  1.1123 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.1124 +    return result;
  1.1125 +  }
  1.1126 +
  1.1127 +  if (r1 != r2) {
  1.1128 +    fail("Top of redo stack changed. (%d)\n", result);
  1.1129 +    return NS_ERROR_FAILURE;
  1.1130 +  }
  1.1131 +
  1.1132 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1133 +
  1.1134 +  if (NS_FAILED(result)) {
  1.1135 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.1136 +         result);
  1.1137 +    return result;
  1.1138 +  }
  1.1139 +
  1.1140 +  if (numitems != 1) {
  1.1141 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.1142 +         numitems, result);
  1.1143 +    return NS_ERROR_FAILURE;
  1.1144 +  }
  1.1145 +
  1.1146 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.1147 +
  1.1148 +  if (NS_FAILED(result)) {
  1.1149 +    fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.1150 +         result);
  1.1151 +    return result;
  1.1152 +  }
  1.1153 +
  1.1154 +  if (numitems != 0) {
  1.1155 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.1156 +         numitems, result);
  1.1157 +    return NS_ERROR_FAILURE;
  1.1158 +  }
  1.1159 +
  1.1160 +  result = mgr->Clear();
  1.1161 +  if (NS_FAILED(result)) {
  1.1162 +    fail("Clear() failed. (%d)\n", result);
  1.1163 +    return result;
  1.1164 +  }
  1.1165 +
  1.1166 +  passed("Test coalescing of transactions");
  1.1167 +
  1.1168 +  /*******************************************************************
  1.1169 +   *
  1.1170 +   * Execute 20 transactions. Afterwards, we should have 10
  1.1171 +   * transactions on the undo stack:
  1.1172 +   *
  1.1173 +   *******************************************************************/
  1.1174 +
  1.1175 +  for (i = 1; i <= 20; i++) {
  1.1176 +    tximpl = factory->create(mgr, NONE_FLAG);
  1.1177 +
  1.1178 +    if (!tximpl) {
  1.1179 +      fail("Failed to allocate transaction %d.\n", i);
  1.1180 +      return NS_ERROR_OUT_OF_MEMORY;
  1.1181 +    }
  1.1182 +
  1.1183 +    tx = 0;
  1.1184 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.1185 +    if (NS_FAILED(result)) {
  1.1186 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.1187 +           i, result);
  1.1188 +      return result;
  1.1189 +    }
  1.1190 +
  1.1191 +    result = mgr->DoTransaction(tx);
  1.1192 +    if (NS_FAILED(result)) {
  1.1193 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.1194 +      return result;
  1.1195 +    }
  1.1196 +
  1.1197 +    tx->Release();
  1.1198 +  }
  1.1199 +
  1.1200 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1201 +
  1.1202 +  if (NS_FAILED(result)) {
  1.1203 +    fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
  1.1204 +         result);
  1.1205 +    return result;
  1.1206 +  }
  1.1207 +
  1.1208 +  if (numitems != 10) {
  1.1209 +    fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  1.1210 +         numitems, result);
  1.1211 +    return NS_ERROR_FAILURE;
  1.1212 +  }
  1.1213 +
  1.1214 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.1215 +
  1.1216 +  if (NS_FAILED(result)) {
  1.1217 +    fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.1218 +         result);
  1.1219 +    return result;
  1.1220 +  }
  1.1221 +
  1.1222 +  if (numitems != 0) {
  1.1223 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.1224 +         numitems, result);
  1.1225 +    return NS_ERROR_FAILURE;
  1.1226 +  }
  1.1227 +
  1.1228 +  passed("Execute 20 transactions");
  1.1229 +
  1.1230 +  /*******************************************************************
  1.1231 +   *
  1.1232 +   * Execute 20 transient transactions. Afterwards, we should still
  1.1233 +   * have the same 10 transactions on the undo stack:
  1.1234 +   *
  1.1235 +   *******************************************************************/
  1.1236 +
  1.1237 +  u1 = u2 = r1 = r2 = 0;
  1.1238 +
  1.1239 +  result = mgr->PeekUndoStack(&u1);
  1.1240 +
  1.1241 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.1242 +
  1.1243 +  if (NS_FAILED(result)) {
  1.1244 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.1245 +    return result;
  1.1246 +  }
  1.1247 +
  1.1248 +  result = mgr->PeekRedoStack(&r1);
  1.1249 +
  1.1250 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.1251 +
  1.1252 +  if (NS_FAILED(result)) {
  1.1253 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.1254 +    return result;
  1.1255 +  }
  1.1256 +
  1.1257 +  for (i = 1; i <= 20; i++) {
  1.1258 +    tximpl = factory->create(mgr, TRANSIENT_FLAG);
  1.1259 +
  1.1260 +    if (!tximpl) {
  1.1261 +      fail("Failed to allocate transaction %d.\n", i);
  1.1262 +      return NS_ERROR_OUT_OF_MEMORY;
  1.1263 +    }
  1.1264 +
  1.1265 +    tx = 0;
  1.1266 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.1267 +    if (NS_FAILED(result)) {
  1.1268 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.1269 +           i, result);
  1.1270 +      return result;
  1.1271 +    }
  1.1272 +
  1.1273 +    result = mgr->DoTransaction(tx);
  1.1274 +    if (NS_FAILED(result)) {
  1.1275 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.1276 +      return result;
  1.1277 +    }
  1.1278 +
  1.1279 +    tx->Release();
  1.1280 +  }
  1.1281 +
  1.1282 +  result = mgr->PeekUndoStack(&u2);
  1.1283 +
  1.1284 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.1285 +
  1.1286 +  if (NS_FAILED(result)) {
  1.1287 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.1288 +    return result;
  1.1289 +  }
  1.1290 +
  1.1291 +  if (u1 != u2) {
  1.1292 +    fail("Top of undo stack changed. (%d)\n", result);
  1.1293 +    return NS_ERROR_FAILURE;
  1.1294 +  }
  1.1295 +
  1.1296 +  result = mgr->PeekRedoStack(&r2);
  1.1297 +
  1.1298 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.1299 +
  1.1300 +  if (NS_FAILED(result)) {
  1.1301 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.1302 +    return result;
  1.1303 +  }
  1.1304 +
  1.1305 +  if (r1 != r2) {
  1.1306 +    fail("Top of redo stack changed. (%d)\n", result);
  1.1307 +    return NS_ERROR_FAILURE;
  1.1308 +  }
  1.1309 +
  1.1310 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1311 +
  1.1312 +  if (NS_FAILED(result)) {
  1.1313 +    fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
  1.1314 +         result);
  1.1315 +    return result;
  1.1316 +  }
  1.1317 +
  1.1318 +  if (numitems != 10) {
  1.1319 +    fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  1.1320 +         numitems, result);
  1.1321 +    return NS_ERROR_FAILURE;
  1.1322 +  }
  1.1323 +
  1.1324 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.1325 +
  1.1326 +  if (NS_FAILED(result)) {
  1.1327 +    fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.1328 +         result);
  1.1329 +    return result;
  1.1330 +  }
  1.1331 +
  1.1332 +  if (numitems != 0) {
  1.1333 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.1334 +         numitems, result);
  1.1335 +    return NS_ERROR_FAILURE;
  1.1336 +  }
  1.1337 +
  1.1338 +  passed("Execute 20 transient transactions");
  1.1339 +
  1.1340 +  /*******************************************************************
  1.1341 +   *
  1.1342 +   * Undo 4 transactions. Afterwards, we should have 6 transactions
  1.1343 +   * on the undo stack, and 4 on the redo stack:
  1.1344 +   *
  1.1345 +   *******************************************************************/
  1.1346 +
  1.1347 +  for (i = 1; i <= 4; i++) {
  1.1348 +    result = mgr->UndoTransaction();
  1.1349 +    if (NS_FAILED(result)) {
  1.1350 +      fail("Failed to undo transaction %d. (%d)\n", i, result);
  1.1351 +      return result;
  1.1352 +    }
  1.1353 +  }
  1.1354 +
  1.1355 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1356 +
  1.1357 +  if (NS_FAILED(result)) {
  1.1358 +    fail("GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
  1.1359 +         result);
  1.1360 +    return result;
  1.1361 +  }
  1.1362 +
  1.1363 +  if (numitems != 6) {
  1.1364 +    fail("GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
  1.1365 +         numitems, result);
  1.1366 +    return NS_ERROR_FAILURE;
  1.1367 +  }
  1.1368 +
  1.1369 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.1370 +
  1.1371 +  if (NS_FAILED(result)) {
  1.1372 +    fail("GetNumberOfRedoItems() on redo stack with 4 items failed. (%d)\n",
  1.1373 +         result);
  1.1374 +    return result;
  1.1375 +  }
  1.1376 +
  1.1377 +  if (numitems != 4) {
  1.1378 +    fail("GetNumberOfRedoItems() expected 4 got %d. (%d)\n",
  1.1379 +         numitems, result);
  1.1380 +    return NS_ERROR_FAILURE;
  1.1381 +  }
  1.1382 +
  1.1383 +  passed("Undo 4 transactions");
  1.1384 +
  1.1385 +  /*******************************************************************
  1.1386 +   *
  1.1387 +   * Redo 2 transactions. Afterwards, we should have 8 transactions
  1.1388 +   * on the undo stack, and 2 on the redo stack:
  1.1389 +   *
  1.1390 +   *******************************************************************/
  1.1391 +
  1.1392 +  for (i = 1; i <= 2; ++i) {
  1.1393 +    result = mgr->RedoTransaction();
  1.1394 +    if (NS_FAILED(result)) {
  1.1395 +      fail("Failed to redo transaction %d. (%d)\n", i, result);
  1.1396 +      return result;
  1.1397 +    }
  1.1398 +  }
  1.1399 +
  1.1400 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1401 +
  1.1402 +  if (NS_FAILED(result)) {
  1.1403 +    fail("GetNumberOfUndoItems() on undo stack with 8 items failed. (%d)\n",
  1.1404 +         result);
  1.1405 +    return result;
  1.1406 +  }
  1.1407 +
  1.1408 +  if (numitems != 8) {
  1.1409 +    fail("GetNumberOfUndoItems() expected 8 got %d. (%d)\n",
  1.1410 +         numitems, result);
  1.1411 +    return NS_ERROR_FAILURE;
  1.1412 +  }
  1.1413 +
  1.1414 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.1415 +
  1.1416 +  if (NS_FAILED(result)) {
  1.1417 +    fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
  1.1418 +         result);
  1.1419 +    return result;
  1.1420 +  }
  1.1421 +
  1.1422 +  if (numitems != 2) {
  1.1423 +    fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
  1.1424 +         numitems, result);
  1.1425 +    return NS_ERROR_FAILURE;
  1.1426 +  }
  1.1427 +
  1.1428 +  passed("Redo 2 transactions");
  1.1429 +
  1.1430 +  /*******************************************************************
  1.1431 +   *
  1.1432 +   * Execute a new transaction. The redo stack should get pruned!
  1.1433 +   *
  1.1434 +   *******************************************************************/
  1.1435 +
  1.1436 +  tximpl = factory->create(mgr, NONE_FLAG);
  1.1437 +
  1.1438 +  if (!tximpl) {
  1.1439 +    fail("Failed to allocate transaction.\n");
  1.1440 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1441 +  }
  1.1442 +
  1.1443 +  tx = 0;
  1.1444 +
  1.1445 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.1446 +
  1.1447 +  if (NS_FAILED(result)) {
  1.1448 +    fail("QueryInterface() failed for transaction. (%d)\n", result);
  1.1449 +    return result;
  1.1450 +  }
  1.1451 +
  1.1452 +  result = mgr->DoTransaction(tx);
  1.1453 +  if (NS_FAILED(result)) {
  1.1454 +    fail("Failed to execute transaction. (%d)\n", result);
  1.1455 +    return result;
  1.1456 +  }
  1.1457 +
  1.1458 +  tx->Release();
  1.1459 +
  1.1460 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1461 +
  1.1462 +  if (NS_FAILED(result)) {
  1.1463 +    fail("GetNumberOfUndoItems() on undo stack with 9 items failed. (%d)\n",
  1.1464 +         result);
  1.1465 +    return result;
  1.1466 +  }
  1.1467 +
  1.1468 +  if (numitems != 9) {
  1.1469 +    fail("GetNumberOfUndoItems() expected 9 got %d. (%d)\n",
  1.1470 +         numitems, result);
  1.1471 +    return NS_ERROR_FAILURE;
  1.1472 +  }
  1.1473 +
  1.1474 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.1475 +
  1.1476 +  if (NS_FAILED(result)) {
  1.1477 +    fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.1478 +         result);
  1.1479 +    return result;
  1.1480 +  }
  1.1481 +
  1.1482 +  if (numitems != 0) {
  1.1483 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.1484 +         numitems, result);
  1.1485 +    return NS_ERROR_FAILURE;
  1.1486 +  }
  1.1487 +
  1.1488 +  passed("Check if new transactions prune the redo stack");
  1.1489 +
  1.1490 +  /*******************************************************************
  1.1491 +   *
  1.1492 +   * Undo 4 transactions then clear the undo and redo stacks.
  1.1493 +   *
  1.1494 +   *******************************************************************/
  1.1495 +
  1.1496 +  for (i = 1; i <= 4; ++i) {
  1.1497 +    result = mgr->UndoTransaction();
  1.1498 +    if (NS_FAILED(result)) {
  1.1499 +      fail("Failed to undo transaction %d. (%d)\n", i, result);
  1.1500 +      return result;
  1.1501 +    }
  1.1502 +  }
  1.1503 +
  1.1504 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1505 +
  1.1506 +  if (NS_FAILED(result)) {
  1.1507 +    fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
  1.1508 +         result);
  1.1509 +    return result;
  1.1510 +  }
  1.1511 +
  1.1512 +  if (numitems != 5) {
  1.1513 +    fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
  1.1514 +         numitems, result);
  1.1515 +    return NS_ERROR_FAILURE;
  1.1516 +  }
  1.1517 +
  1.1518 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.1519 +
  1.1520 +  if (NS_FAILED(result)) {
  1.1521 +    fail("GetNumberOfRedoItems() on redo stack with 4 items failed. (%d)\n",
  1.1522 +         result);
  1.1523 +    return result;
  1.1524 +  }
  1.1525 +
  1.1526 +  if (numitems != 4) {
  1.1527 +    fail("GetNumberOfRedoItems() expected 4 got %d. (%d)\n",
  1.1528 +         numitems, result);
  1.1529 +    return NS_ERROR_FAILURE;
  1.1530 +  }
  1.1531 +
  1.1532 +  result = mgr->Clear();
  1.1533 +  if (NS_FAILED(result)) {
  1.1534 +    fail("Clear() failed. (%d)\n", result);
  1.1535 +    return result;
  1.1536 +  }
  1.1537 +
  1.1538 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1539 +
  1.1540 +  if (NS_FAILED(result)) {
  1.1541 +    fail("GetNumberOfUndoItems() on cleared undo stack failed. (%d)\n",
  1.1542 +         result);
  1.1543 +    return result;
  1.1544 +  }
  1.1545 +
  1.1546 +  if (numitems != 0) {
  1.1547 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.1548 +         numitems, result);
  1.1549 +    return NS_ERROR_FAILURE;
  1.1550 +  }
  1.1551 +
  1.1552 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.1553 +
  1.1554 +  if (NS_FAILED(result)) {
  1.1555 +    fail("GetNumberOfRedoItems() on cleared redo stack failed. (%d)\n",
  1.1556 +         result);
  1.1557 +    return result;
  1.1558 +  }
  1.1559 +
  1.1560 +  if (numitems != 0) {
  1.1561 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.1562 +         numitems, result);
  1.1563 +    return NS_ERROR_FAILURE;
  1.1564 +  }
  1.1565 +
  1.1566 +  passed("Undo 4 transactions then clear the undo and redo stacks");
  1.1567 +
  1.1568 +  /*******************************************************************
  1.1569 +   *
  1.1570 +   * Execute 5 transactions.
  1.1571 +   *
  1.1572 +   *******************************************************************/
  1.1573 +
  1.1574 +  for (i = 1; i <= 5; i++) {
  1.1575 +    tximpl = factory->create(mgr, NONE_FLAG);
  1.1576 +
  1.1577 +    if (!tximpl) {
  1.1578 +      fail("Failed to allocate transaction %d.\n", i);
  1.1579 +      return NS_ERROR_OUT_OF_MEMORY;
  1.1580 +    }
  1.1581 +
  1.1582 +    tx = 0;
  1.1583 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.1584 +    if (NS_FAILED(result)) {
  1.1585 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.1586 +           i, result);
  1.1587 +      return result;
  1.1588 +    }
  1.1589 +
  1.1590 +    result = mgr->DoTransaction(tx);
  1.1591 +    if (NS_FAILED(result)) {
  1.1592 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.1593 +      return result;
  1.1594 +    }
  1.1595 +
  1.1596 +    tx->Release();
  1.1597 +  }
  1.1598 +
  1.1599 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1600 +
  1.1601 +  if (NS_FAILED(result)) {
  1.1602 +    fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
  1.1603 +         result);
  1.1604 +    return result;
  1.1605 +  }
  1.1606 +
  1.1607 +  if (numitems != 5) {
  1.1608 +    fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
  1.1609 +         numitems, result);
  1.1610 +    return NS_ERROR_FAILURE;
  1.1611 +  }
  1.1612 +
  1.1613 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.1614 +
  1.1615 +  if (NS_FAILED(result)) {
  1.1616 +    fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.1617 +         result);
  1.1618 +    return result;
  1.1619 +  }
  1.1620 +
  1.1621 +  if (numitems != 0) {
  1.1622 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.1623 +         numitems, result);
  1.1624 +    return NS_ERROR_FAILURE;
  1.1625 +  }
  1.1626 +
  1.1627 +  passed("Execute 5 transactions");
  1.1628 +
  1.1629 +  /*******************************************************************
  1.1630 +   *
  1.1631 +   * Test transaction DoTransaction() error:
  1.1632 +   *
  1.1633 +   *******************************************************************/
  1.1634 +
  1.1635 +  tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
  1.1636 +
  1.1637 +  if (!tximpl) {
  1.1638 +    fail("Failed to allocate transaction.\n");
  1.1639 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1640 +  }
  1.1641 +
  1.1642 +  tx = 0;
  1.1643 +
  1.1644 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.1645 +
  1.1646 +  if (NS_FAILED(result)) {
  1.1647 +    fail("QueryInterface() failed for transaction. (%d)\n", result);
  1.1648 +    return result;
  1.1649 +  }
  1.1650 +
  1.1651 +  u1 = u2 = r1 = r2 = 0;
  1.1652 +
  1.1653 +  result = mgr->PeekUndoStack(&u1);
  1.1654 +
  1.1655 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.1656 +
  1.1657 +  if (NS_FAILED(result)) {
  1.1658 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.1659 +    return result;
  1.1660 +  }
  1.1661 +
  1.1662 +  result = mgr->PeekRedoStack(&r1);
  1.1663 +
  1.1664 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.1665 +
  1.1666 +  if (NS_FAILED(result)) {
  1.1667 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.1668 +    return result;
  1.1669 +  }
  1.1670 +
  1.1671 +  result = mgr->DoTransaction(tx);
  1.1672 +
  1.1673 +  if (result != NS_ERROR_FAILURE) {
  1.1674 +    fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1.1675 +    return result;
  1.1676 +  }
  1.1677 +
  1.1678 +  tx->Release();
  1.1679 +
  1.1680 +  result = mgr->PeekUndoStack(&u2);
  1.1681 +
  1.1682 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.1683 +
  1.1684 +  if (NS_FAILED(result)) {
  1.1685 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.1686 +    return result;
  1.1687 +  }
  1.1688 +
  1.1689 +  if (u1 != u2) {
  1.1690 +    fail("Top of undo stack changed. (%d)\n", result);
  1.1691 +    return NS_ERROR_FAILURE;
  1.1692 +  }
  1.1693 +
  1.1694 +  result = mgr->PeekRedoStack(&r2);
  1.1695 +
  1.1696 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.1697 +
  1.1698 +  if (NS_FAILED(result)) {
  1.1699 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.1700 +    return result;
  1.1701 +  }
  1.1702 +
  1.1703 +  if (r1 != r2) {
  1.1704 +    fail("Top of redo stack changed. (%d)\n", result);
  1.1705 +    return NS_ERROR_FAILURE;
  1.1706 +  }
  1.1707 +
  1.1708 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1709 +
  1.1710 +  if (NS_FAILED(result)) {
  1.1711 +    fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
  1.1712 +         result);
  1.1713 +    return result;
  1.1714 +  }
  1.1715 +
  1.1716 +  if (numitems != 5) {
  1.1717 +    fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
  1.1718 +         numitems, result);
  1.1719 +    return NS_ERROR_FAILURE;
  1.1720 +  }
  1.1721 +
  1.1722 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.1723 +
  1.1724 +  if (NS_FAILED(result)) {
  1.1725 +    fail("GetNumberOfRedoItems() on empty redo stack. (%d)\n",
  1.1726 +         result);
  1.1727 +    return result;
  1.1728 +  }
  1.1729 +
  1.1730 +  if (numitems != 0) {
  1.1731 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.1732 +         numitems, result);
  1.1733 +    return NS_ERROR_FAILURE;
  1.1734 +  }
  1.1735 +
  1.1736 +  passed("Test transaction DoTransaction() error");
  1.1737 +
  1.1738 +  /*******************************************************************
  1.1739 +   *
  1.1740 +   * Test transaction UndoTransaction() error:
  1.1741 +   *
  1.1742 +   *******************************************************************/
  1.1743 +
  1.1744 +  tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
  1.1745 +
  1.1746 +  if (!tximpl) {
  1.1747 +    fail("Failed to allocate transaction.\n");
  1.1748 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1749 +  }
  1.1750 +
  1.1751 +  tx = 0;
  1.1752 +
  1.1753 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.1754 +
  1.1755 +  if (NS_FAILED(result)) {
  1.1756 +    fail("QueryInterface() failed for transaction. (%d)\n", result);
  1.1757 +    return result;
  1.1758 +  }
  1.1759 +
  1.1760 +  result = mgr->DoTransaction(tx);
  1.1761 +
  1.1762 +  if (NS_FAILED(result)) {
  1.1763 +    fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1.1764 +    return result;
  1.1765 +  }
  1.1766 +
  1.1767 +  tx->Release();
  1.1768 +
  1.1769 +  u1 = u2 = r1 = r2 = 0;
  1.1770 +
  1.1771 +  result = mgr->PeekUndoStack(&u1);
  1.1772 +
  1.1773 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.1774 +
  1.1775 +  if (NS_FAILED(result)) {
  1.1776 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.1777 +    return result;
  1.1778 +  }
  1.1779 +
  1.1780 +  result = mgr->PeekRedoStack(&r1);
  1.1781 +
  1.1782 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.1783 +
  1.1784 +  if (NS_FAILED(result)) {
  1.1785 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.1786 +    return result;
  1.1787 +  }
  1.1788 +
  1.1789 +  result = mgr->UndoTransaction();
  1.1790 +
  1.1791 +  if (result != NS_ERROR_FAILURE) {
  1.1792 +    fail("UndoTransaction() returned unexpected error. (%d)\n", result);
  1.1793 +    return result;
  1.1794 +  }
  1.1795 +
  1.1796 +  result = mgr->PeekUndoStack(&u2);
  1.1797 +
  1.1798 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.1799 +
  1.1800 +  if (NS_FAILED(result)) {
  1.1801 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.1802 +    return result;
  1.1803 +  }
  1.1804 +
  1.1805 +  if (u1 != u2) {
  1.1806 +    fail("Top of undo stack changed. (%d)\n", result);
  1.1807 +    return NS_ERROR_FAILURE;
  1.1808 +  }
  1.1809 +
  1.1810 +  result = mgr->PeekRedoStack(&r2);
  1.1811 +
  1.1812 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.1813 +
  1.1814 +  if (NS_FAILED(result)) {
  1.1815 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.1816 +    return result;
  1.1817 +  }
  1.1818 +
  1.1819 +  if (r1 != r2) {
  1.1820 +    fail("Top of redo stack changed. (%d)\n", result);
  1.1821 +    return NS_ERROR_FAILURE;
  1.1822 +  }
  1.1823 +
  1.1824 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1825 +
  1.1826 +  if (NS_FAILED(result)) {
  1.1827 +    fail("GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
  1.1828 +         result);
  1.1829 +    return result;
  1.1830 +  }
  1.1831 +
  1.1832 +  if (numitems != 6) {
  1.1833 +    fail("GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
  1.1834 +         numitems, result);
  1.1835 +    return NS_ERROR_FAILURE;
  1.1836 +  }
  1.1837 +
  1.1838 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.1839 +
  1.1840 +  if (NS_FAILED(result)) {
  1.1841 +    fail("GetNumberOfRedoItems() on empty redo stack. (%d)\n",
  1.1842 +         result);
  1.1843 +    return result;
  1.1844 +  }
  1.1845 +
  1.1846 +  if (numitems != 0) {
  1.1847 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.1848 +         numitems, result);
  1.1849 +    return NS_ERROR_FAILURE;
  1.1850 +  }
  1.1851 +
  1.1852 +  passed("Test transaction UndoTransaction() error");
  1.1853 +
  1.1854 +  /*******************************************************************
  1.1855 +   *
  1.1856 +   * Test transaction RedoTransaction() error:
  1.1857 +   *
  1.1858 +   *******************************************************************/
  1.1859 +
  1.1860 +  tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
  1.1861 +
  1.1862 +  if (!tximpl) {
  1.1863 +    fail("Failed to allocate transaction.\n");
  1.1864 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1865 +  }
  1.1866 +
  1.1867 +  tx = 0;
  1.1868 +
  1.1869 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.1870 +
  1.1871 +  if (NS_FAILED(result)) {
  1.1872 +    fail("QueryInterface() failed for RedoErrorTransaction. (%d)\n",
  1.1873 +         result);
  1.1874 +    return result;
  1.1875 +  }
  1.1876 +
  1.1877 +  result = mgr->DoTransaction(tx);
  1.1878 +
  1.1879 +  if (NS_FAILED(result)) {
  1.1880 +    fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1.1881 +    return result;
  1.1882 +  }
  1.1883 +
  1.1884 +  tx->Release();
  1.1885 +
  1.1886 +  //
  1.1887 +  // Execute a normal transaction to be used in a later test:
  1.1888 +  //
  1.1889 +
  1.1890 +  tximpl = factory->create(mgr, NONE_FLAG);
  1.1891 +
  1.1892 +  if (!tximpl) {
  1.1893 +    fail("Failed to allocate transaction.\n");
  1.1894 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1895 +  }
  1.1896 +
  1.1897 +  tx = 0;
  1.1898 +
  1.1899 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.1900 +
  1.1901 +  if (NS_FAILED(result)) {
  1.1902 +    fail("QueryInterface() failed for transaction. (%d)\n", result);
  1.1903 +    return result;
  1.1904 +  }
  1.1905 +
  1.1906 +  result = mgr->DoTransaction(tx);
  1.1907 +
  1.1908 +  if (NS_FAILED(result)) {
  1.1909 +    fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1.1910 +    return result;
  1.1911 +  }
  1.1912 +
  1.1913 +  tx->Release();
  1.1914 +
  1.1915 +  //
  1.1916 +  // Undo the 2 transactions just executed.
  1.1917 +  //
  1.1918 +
  1.1919 +  for (i = 1; i <= 2; ++i) {
  1.1920 +    result = mgr->UndoTransaction();
  1.1921 +    if (NS_FAILED(result)) {
  1.1922 +      fail("Failed to undo transaction %d. (%d)\n", i, result);
  1.1923 +      return result;
  1.1924 +    }
  1.1925 +  }
  1.1926 +
  1.1927 +  //
  1.1928 +  // The RedoErrorTransaction should now be at the top of the redo stack!
  1.1929 +  //
  1.1930 +
  1.1931 +  u1 = u2 = r1 = r2 = 0;
  1.1932 +
  1.1933 +  result = mgr->PeekUndoStack(&u1);
  1.1934 +
  1.1935 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.1936 +
  1.1937 +  if (NS_FAILED(result)) {
  1.1938 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.1939 +    return result;
  1.1940 +  }
  1.1941 +
  1.1942 +  result = mgr->PeekRedoStack(&r1);
  1.1943 +
  1.1944 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.1945 +
  1.1946 +  if (NS_FAILED(result)) {
  1.1947 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.1948 +    return result;
  1.1949 +  }
  1.1950 +
  1.1951 +  result = mgr->RedoTransaction();
  1.1952 +
  1.1953 +  if (result != NS_ERROR_FAILURE) {
  1.1954 +    fail("RedoTransaction() returned unexpected error. (%d)\n", result);
  1.1955 +    return result;
  1.1956 +  }
  1.1957 +
  1.1958 +  result = mgr->PeekUndoStack(&u2);
  1.1959 +
  1.1960 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.1961 +
  1.1962 +  if (NS_FAILED(result)) {
  1.1963 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.1964 +    return result;
  1.1965 +  }
  1.1966 +
  1.1967 +  if (u1 != u2) {
  1.1968 +    fail("Top of undo stack changed. (%d)\n", result);
  1.1969 +    return NS_ERROR_FAILURE;
  1.1970 +  }
  1.1971 +
  1.1972 +  result = mgr->PeekRedoStack(&r2);
  1.1973 +
  1.1974 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.1975 +
  1.1976 +  if (NS_FAILED(result)) {
  1.1977 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.1978 +    return result;
  1.1979 +  }
  1.1980 +
  1.1981 +  if (r1 != r2) {
  1.1982 +    fail("Top of redo stack changed. (%d)\n", result);
  1.1983 +    return NS_ERROR_FAILURE;
  1.1984 +  }
  1.1985 +
  1.1986 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.1987 +
  1.1988 +  if (NS_FAILED(result)) {
  1.1989 +    fail("GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
  1.1990 +         result);
  1.1991 +    return result;
  1.1992 +  }
  1.1993 +
  1.1994 +  if (numitems != 6) {
  1.1995 +    fail("GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
  1.1996 +         numitems, result);
  1.1997 +    return NS_ERROR_FAILURE;
  1.1998 +  }
  1.1999 +
  1.2000 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.2001 +
  1.2002 +  if (NS_FAILED(result)) {
  1.2003 +    fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
  1.2004 +         result);
  1.2005 +    return result;
  1.2006 +  }
  1.2007 +
  1.2008 +  if (numitems != 2) {
  1.2009 +    fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
  1.2010 +         numitems, result);
  1.2011 +    return NS_ERROR_FAILURE;
  1.2012 +  }
  1.2013 +
  1.2014 +  passed("Test transaction RedoTransaction() error");
  1.2015 +
  1.2016 +  /*******************************************************************
  1.2017 +   *
  1.2018 +   * Make sure that setting the transaction manager's max transaction
  1.2019 +   * count to zero, clears both the undo and redo stacks, and executes
  1.2020 +   * all new commands without pushing them on the undo stack!
  1.2021 +   *
  1.2022 +   *******************************************************************/
  1.2023 +
  1.2024 +  result = mgr->SetMaxTransactionCount(0);
  1.2025 +
  1.2026 +  if (NS_FAILED(result)) {
  1.2027 +    fail("SetMaxTransactionCount(0) failed. (%d)\n", result);
  1.2028 +    return result;
  1.2029 +  }
  1.2030 +
  1.2031 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2032 +
  1.2033 +  if (NS_FAILED(result)) {
  1.2034 +    fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.2035 +         result);
  1.2036 +    return result;
  1.2037 +  }
  1.2038 +
  1.2039 +  if (numitems != 0) {
  1.2040 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.2041 +         numitems, result);
  1.2042 +    return NS_ERROR_FAILURE;
  1.2043 +  }
  1.2044 +
  1.2045 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.2046 +
  1.2047 +  if (NS_FAILED(result)) {
  1.2048 +    fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.2049 +         result);
  1.2050 +    return result;
  1.2051 +  }
  1.2052 +
  1.2053 +  if (numitems != 0) {
  1.2054 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.2055 +         numitems, result);
  1.2056 +    return NS_ERROR_FAILURE;
  1.2057 +  }
  1.2058 +
  1.2059 +  for (i = 1; i <= 20; i++) {
  1.2060 +    tximpl = factory->create(mgr, NONE_FLAG);
  1.2061 +
  1.2062 +    if (!tximpl) {
  1.2063 +      fail("Failed to allocate transaction %d.\n", i);
  1.2064 +      return NS_ERROR_OUT_OF_MEMORY;
  1.2065 +    }
  1.2066 +
  1.2067 +    tx = 0;
  1.2068 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.2069 +    if (NS_FAILED(result)) {
  1.2070 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.2071 +           i, result);
  1.2072 +      return result;
  1.2073 +    }
  1.2074 +
  1.2075 +    result = mgr->DoTransaction(tx);
  1.2076 +    if (NS_FAILED(result)) {
  1.2077 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.2078 +      return result;
  1.2079 +    }
  1.2080 +
  1.2081 +    tx->Release();
  1.2082 +
  1.2083 +    result = mgr->GetNumberOfUndoItems(&numitems);
  1.2084 +
  1.2085 +    if (NS_FAILED(result)) {
  1.2086 +      fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.2087 +           result);
  1.2088 +      return result;
  1.2089 +    }
  1.2090 +
  1.2091 +    if (numitems != 0) {
  1.2092 +      fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.2093 +           numitems, result);
  1.2094 +      return NS_ERROR_FAILURE;
  1.2095 +    }
  1.2096 +
  1.2097 +    result = mgr->GetNumberOfRedoItems(&numitems);
  1.2098 +
  1.2099 +    if (NS_FAILED(result)) {
  1.2100 +      fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.2101 +           result);
  1.2102 +      return result;
  1.2103 +    }
  1.2104 +
  1.2105 +    if (numitems != 0) {
  1.2106 +      fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.2107 +           numitems, result);
  1.2108 +      return NS_ERROR_FAILURE;
  1.2109 +    }
  1.2110 +  }
  1.2111 +
  1.2112 +  passed("Test max transaction count of zero");
  1.2113 +
  1.2114 +  /*******************************************************************
  1.2115 +   *
  1.2116 +   * Make sure that setting the transaction manager's max transaction
  1.2117 +   * count to something greater than the number of transactions on
  1.2118 +   * both the undo and redo stacks causes no pruning of the stacks:
  1.2119 +   *
  1.2120 +   *******************************************************************/
  1.2121 +
  1.2122 +  result = mgr->SetMaxTransactionCount(-1);
  1.2123 +
  1.2124 +  if (NS_FAILED(result)) {
  1.2125 +    fail("SetMaxTransactionCount(-1) failed. (%d)\n", result);
  1.2126 +    return result;
  1.2127 +  }
  1.2128 +
  1.2129 +  // Push 20 transactions on the undo stack:
  1.2130 +
  1.2131 +  for (i = 1; i <= 20; i++) {
  1.2132 +    tximpl = factory->create(mgr, NONE_FLAG);
  1.2133 +
  1.2134 +    if (!tximpl) {
  1.2135 +      fail("Failed to allocate transaction %d.\n", i);
  1.2136 +      return NS_ERROR_OUT_OF_MEMORY;
  1.2137 +    }
  1.2138 +
  1.2139 +    tx = 0;
  1.2140 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.2141 +    if (NS_FAILED(result)) {
  1.2142 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.2143 +           i, result);
  1.2144 +      return result;
  1.2145 +    }
  1.2146 +
  1.2147 +    result = mgr->DoTransaction(tx);
  1.2148 +    if (NS_FAILED(result)) {
  1.2149 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.2150 +      return result;
  1.2151 +    }
  1.2152 +
  1.2153 +    tx->Release();
  1.2154 +
  1.2155 +    result = mgr->GetNumberOfUndoItems(&numitems);
  1.2156 +
  1.2157 +    if (NS_FAILED(result)) {
  1.2158 +      fail("GetNumberOfUndoItems() on undo stack with %d items failed. (%d)\n",
  1.2159 +           i, result);
  1.2160 +      return result;
  1.2161 +    }
  1.2162 +
  1.2163 +    if (numitems != i) {
  1.2164 +      fail("GetNumberOfUndoItems() expected %d got %d. (%d)\n",
  1.2165 +           i, numitems, result);
  1.2166 +      return NS_ERROR_FAILURE;
  1.2167 +    }
  1.2168 +
  1.2169 +    result = mgr->GetNumberOfRedoItems(&numitems);
  1.2170 +
  1.2171 +    if (NS_FAILED(result)) {
  1.2172 +      fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.2173 +           result);
  1.2174 +      return result;
  1.2175 +    }
  1.2176 +
  1.2177 +    if (numitems != 0) {
  1.2178 +      fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.2179 +           numitems, result);
  1.2180 +      return NS_ERROR_FAILURE;
  1.2181 +    }
  1.2182 +  }
  1.2183 +
  1.2184 +  for (i = 1; i <= 10; i++) {
  1.2185 +
  1.2186 +    result = mgr->UndoTransaction();
  1.2187 +    if (NS_FAILED(result)) {
  1.2188 +      fail("Failed to undo transaction %d. (%d)\n", i, result);
  1.2189 +      return result;
  1.2190 +    }
  1.2191 +  }
  1.2192 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2193 +
  1.2194 +  if (NS_FAILED(result)) {
  1.2195 +    fail("GetNumberOfUndoItems() on empty undo stack with 10 items failed. (%d)\n",
  1.2196 +         result);
  1.2197 +    return result;
  1.2198 +  }
  1.2199 +
  1.2200 +  if (numitems != 10) {
  1.2201 +    fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  1.2202 +         numitems, result);
  1.2203 +    return NS_ERROR_FAILURE;
  1.2204 +  }
  1.2205 +
  1.2206 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.2207 +
  1.2208 +  if (NS_FAILED(result)) {
  1.2209 +    fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
  1.2210 +         result);
  1.2211 +    return result;
  1.2212 +  }
  1.2213 +
  1.2214 +  if (numitems != 10) {
  1.2215 +    fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
  1.2216 +         numitems, result);
  1.2217 +    return NS_ERROR_FAILURE;
  1.2218 +  }
  1.2219 +
  1.2220 +  u1 = u2 = r1 = r2 = 0;
  1.2221 +
  1.2222 +  result = mgr->PeekUndoStack(&u1);
  1.2223 +
  1.2224 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.2225 +
  1.2226 +  if (NS_FAILED(result)) {
  1.2227 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.2228 +    return result;
  1.2229 +  }
  1.2230 +
  1.2231 +  result = mgr->PeekRedoStack(&r1);
  1.2232 +
  1.2233 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.2234 +
  1.2235 +  if (NS_FAILED(result)) {
  1.2236 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.2237 +    return result;
  1.2238 +  }
  1.2239 +
  1.2240 +  result = mgr->SetMaxTransactionCount(25);
  1.2241 +
  1.2242 +  if (NS_FAILED(result)) {
  1.2243 +    fail("SetMaxTransactionCount(25) failed. (%d)\n", result);
  1.2244 +    return result;
  1.2245 +  }
  1.2246 +
  1.2247 +  result = mgr->PeekUndoStack(&u2);
  1.2248 +
  1.2249 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.2250 +
  1.2251 +  if (NS_FAILED(result)) {
  1.2252 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.2253 +    return result;
  1.2254 +  }
  1.2255 +
  1.2256 +  if (u1 != u2) {
  1.2257 +    fail("Top of undo stack changed. (%d)\n", result);
  1.2258 +    return NS_ERROR_FAILURE;
  1.2259 +  }
  1.2260 +
  1.2261 +  result = mgr->PeekRedoStack(&r2);
  1.2262 +
  1.2263 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.2264 +
  1.2265 +  if (NS_FAILED(result)) {
  1.2266 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.2267 +    return result;
  1.2268 +  }
  1.2269 +
  1.2270 +  if (r1 != r2) {
  1.2271 +    fail("Top of redo stack changed. (%d)\n", result);
  1.2272 +    return NS_ERROR_FAILURE;
  1.2273 +  }
  1.2274 +
  1.2275 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2276 +
  1.2277 +  if (NS_FAILED(result)) {
  1.2278 +    fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
  1.2279 +         result);
  1.2280 +    return result;
  1.2281 +  }
  1.2282 +
  1.2283 +  if (numitems != 10) {
  1.2284 +    fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  1.2285 +         numitems, result);
  1.2286 +    return NS_ERROR_FAILURE;
  1.2287 +  }
  1.2288 +
  1.2289 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.2290 +
  1.2291 +  if (NS_FAILED(result)) {
  1.2292 +    fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
  1.2293 +         result);
  1.2294 +    return result;
  1.2295 +  }
  1.2296 +
  1.2297 +  if (numitems != 10) {
  1.2298 +    fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
  1.2299 +         numitems, result);
  1.2300 +    return NS_ERROR_FAILURE;
  1.2301 +  }
  1.2302 +
  1.2303 +  passed("Test SetMaxTransactionCount() greater than num stack items");
  1.2304 +
  1.2305 +  /*******************************************************************
  1.2306 +   *
  1.2307 +   * Test undo stack pruning by setting the transaction
  1.2308 +   * manager's max transaction count to a number lower than the
  1.2309 +   * number of transactions on both the undo and redo stacks:
  1.2310 +   *
  1.2311 +   *******************************************************************/
  1.2312 +
  1.2313 +  u1 = u2 = r1 = r2 = 0;
  1.2314 +
  1.2315 +  result = mgr->PeekUndoStack(&u1);
  1.2316 +
  1.2317 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.2318 +
  1.2319 +  if (NS_FAILED(result)) {
  1.2320 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.2321 +    return result;
  1.2322 +  }
  1.2323 +
  1.2324 +  result = mgr->PeekRedoStack(&r1);
  1.2325 +
  1.2326 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.2327 +
  1.2328 +  if (NS_FAILED(result)) {
  1.2329 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.2330 +    return result;
  1.2331 +  }
  1.2332 +
  1.2333 +  result = mgr->SetMaxTransactionCount(15);
  1.2334 +
  1.2335 +  if (NS_FAILED(result)) {
  1.2336 +    fail("SetMaxTransactionCount(15) failed. (%d)\n", result);
  1.2337 +    return result;
  1.2338 +  }
  1.2339 +
  1.2340 +  result = mgr->PeekUndoStack(&u2);
  1.2341 +
  1.2342 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.2343 +
  1.2344 +  if (NS_FAILED(result)) {
  1.2345 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.2346 +    return result;
  1.2347 +  }
  1.2348 +
  1.2349 +  if (u1 != u2) {
  1.2350 +    fail("Top of undo stack changed. (%d)\n", result);
  1.2351 +    return NS_ERROR_FAILURE;
  1.2352 +  }
  1.2353 +
  1.2354 +  result = mgr->PeekRedoStack(&r2);
  1.2355 +
  1.2356 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.2357 +
  1.2358 +  if (NS_FAILED(result)) {
  1.2359 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.2360 +    return result;
  1.2361 +  }
  1.2362 +
  1.2363 +  if (r1 != r2) {
  1.2364 +    fail("Top of redo stack changed. (%d)\n", result);
  1.2365 +    return NS_ERROR_FAILURE;
  1.2366 +  }
  1.2367 +
  1.2368 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2369 +
  1.2370 +  if (NS_FAILED(result)) {
  1.2371 +    fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
  1.2372 +           result);
  1.2373 +    return result;
  1.2374 +  }
  1.2375 +
  1.2376 +  if (numitems != 5) {
  1.2377 +    fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
  1.2378 +         numitems, result);
  1.2379 +    return NS_ERROR_FAILURE;
  1.2380 +  }
  1.2381 +
  1.2382 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.2383 +
  1.2384 +  if (NS_FAILED(result)) {
  1.2385 +    fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
  1.2386 +         result);
  1.2387 +    return result;
  1.2388 +  }
  1.2389 +
  1.2390 +  if (numitems != 10) {
  1.2391 +    fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
  1.2392 +         numitems, result);
  1.2393 +    return NS_ERROR_FAILURE;
  1.2394 +  }
  1.2395 +
  1.2396 +  passed("Test SetMaxTransactionCount() pruning undo stack");
  1.2397 +
  1.2398 +  /*******************************************************************
  1.2399 +   *
  1.2400 +   * Test redo stack pruning by setting the transaction
  1.2401 +   * manager's max transaction count to a number lower than the
  1.2402 +   * number of transactions on both the undo and redo stacks:
  1.2403 +   *
  1.2404 +   *******************************************************************/
  1.2405 +
  1.2406 +  u1 = u2 = r1 = r2 = 0;
  1.2407 +
  1.2408 +  result = mgr->PeekUndoStack(&u1);
  1.2409 +
  1.2410 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.2411 +
  1.2412 +  if (NS_FAILED(result)) {
  1.2413 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.2414 +    return result;
  1.2415 +  }
  1.2416 +
  1.2417 +  result = mgr->PeekRedoStack(&r1);
  1.2418 +
  1.2419 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.2420 +
  1.2421 +  if (NS_FAILED(result)) {
  1.2422 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.2423 +    return result;
  1.2424 +  }
  1.2425 +
  1.2426 +  result = mgr->SetMaxTransactionCount(5);
  1.2427 +
  1.2428 +  if (NS_FAILED(result)) {
  1.2429 +    fail("SetMaxTransactionCount(5) failed. (%d)\n", result);
  1.2430 +    return result;
  1.2431 +  }
  1.2432 +
  1.2433 +  result = mgr->PeekUndoStack(&u2);
  1.2434 +
  1.2435 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.2436 +
  1.2437 +  if (NS_FAILED(result)) {
  1.2438 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.2439 +    return result;
  1.2440 +  }
  1.2441 +
  1.2442 +  if (u2) {
  1.2443 +    fail("Unexpected item at top of undo stack. (%d)\n", result);
  1.2444 +    return NS_ERROR_FAILURE;
  1.2445 +  }
  1.2446 +
  1.2447 +  result = mgr->PeekRedoStack(&r2);
  1.2448 +
  1.2449 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.2450 +
  1.2451 +  if (NS_FAILED(result)) {
  1.2452 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.2453 +    return result;
  1.2454 +  }
  1.2455 +
  1.2456 +  if (r1 != r2) {
  1.2457 +    fail("Top of redo stack changed. (%d)\n", result);
  1.2458 +    return NS_ERROR_FAILURE;
  1.2459 +  }
  1.2460 +
  1.2461 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2462 +
  1.2463 +  if (NS_FAILED(result)) {
  1.2464 +    fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.2465 +         result);
  1.2466 +    return result;
  1.2467 +  }
  1.2468 +
  1.2469 +  if (numitems != 0) {
  1.2470 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.2471 +         numitems, result);
  1.2472 +    return NS_ERROR_FAILURE;
  1.2473 +  }
  1.2474 +
  1.2475 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.2476 +
  1.2477 +  if (NS_FAILED(result)) {
  1.2478 +    fail("GetNumberOfRedoItems() on redo stack with 5 items failed. (%d)\n",
  1.2479 +         result);
  1.2480 +    return result;
  1.2481 +  }
  1.2482 +
  1.2483 +  if (numitems != 5) {
  1.2484 +    fail("GetNumberOfRedoItems() expected 5 got %d. (%d)\n",
  1.2485 +         numitems, result);
  1.2486 +    return NS_ERROR_FAILURE;
  1.2487 +  }
  1.2488 +
  1.2489 +  passed("Test SetMaxTransactionCount() pruning redo stack");
  1.2490 +
  1.2491 +  /*******************************************************************
  1.2492 +   *
  1.2493 +   * Release the transaction manager. Any transactions on the undo
  1.2494 +   * and redo stack should automatically be released:
  1.2495 +   *
  1.2496 +   *******************************************************************/
  1.2497 +
  1.2498 +  result = mgr->SetMaxTransactionCount(-1);
  1.2499 +
  1.2500 +  if (NS_FAILED(result)) {
  1.2501 +    fail("SetMaxTransactionCount(-1) failed. (%d)\n", result);
  1.2502 +    return result;
  1.2503 +  }
  1.2504 +
  1.2505 +  // Push 20 transactions on the undo stack:
  1.2506 +
  1.2507 +  for (i = 1; i <= 20; i++) {
  1.2508 +    tximpl = factory->create(mgr, NONE_FLAG);
  1.2509 +
  1.2510 +    if (!tximpl) {
  1.2511 +      fail("Failed to allocate transaction %d.\n", i);
  1.2512 +      return NS_ERROR_OUT_OF_MEMORY;
  1.2513 +    }
  1.2514 +
  1.2515 +    tx = 0;
  1.2516 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.2517 +    if (NS_FAILED(result)) {
  1.2518 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.2519 +           i, result);
  1.2520 +      return result;
  1.2521 +    }
  1.2522 +
  1.2523 +    result = mgr->DoTransaction(tx);
  1.2524 +    if (NS_FAILED(result)) {
  1.2525 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.2526 +      return result;
  1.2527 +    }
  1.2528 +
  1.2529 +    tx->Release();
  1.2530 +
  1.2531 +    result = mgr->GetNumberOfUndoItems(&numitems);
  1.2532 +
  1.2533 +    if (NS_FAILED(result)) {
  1.2534 +      fail("GetNumberOfUndoItems() on undo stack with %d items failed. (%d)\n",
  1.2535 +           i, result);
  1.2536 +      return result;
  1.2537 +    }
  1.2538 +
  1.2539 +    if (numitems != i) {
  1.2540 +      fail("GetNumberOfUndoItems() expected %d got %d. (%d)\n",
  1.2541 +           i, numitems, result);
  1.2542 +      return NS_ERROR_FAILURE;
  1.2543 +    }
  1.2544 +
  1.2545 +    result = mgr->GetNumberOfRedoItems(&numitems);
  1.2546 +
  1.2547 +    if (NS_FAILED(result)) {
  1.2548 +      fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.2549 +           result);
  1.2550 +      return result;
  1.2551 +    }
  1.2552 +
  1.2553 +    if (numitems != 0) {
  1.2554 +      fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.2555 +           numitems, result);
  1.2556 +      return NS_ERROR_FAILURE;
  1.2557 +    }
  1.2558 +  }
  1.2559 +
  1.2560 +  for (i = 1; i <= 10; i++) {
  1.2561 +
  1.2562 +    result = mgr->UndoTransaction();
  1.2563 +    if (NS_FAILED(result)) {
  1.2564 +      fail("Failed to undo transaction %d. (%d)\n", i, result);
  1.2565 +      return result;
  1.2566 +    }
  1.2567 +  }
  1.2568 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2569 +
  1.2570 +  if (NS_FAILED(result)) {
  1.2571 +    fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
  1.2572 +         result);
  1.2573 +    return result;
  1.2574 +  }
  1.2575 +
  1.2576 +  if (numitems != 10) {
  1.2577 +    fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  1.2578 +         numitems, result);
  1.2579 +    return NS_ERROR_FAILURE;
  1.2580 +  }
  1.2581 +
  1.2582 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.2583 +
  1.2584 +  if (NS_FAILED(result)) {
  1.2585 +    fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
  1.2586 +         result);
  1.2587 +    return result;
  1.2588 +  }
  1.2589 +
  1.2590 +  if (numitems != 10) {
  1.2591 +    fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
  1.2592 +         numitems, result);
  1.2593 +    return NS_ERROR_FAILURE;
  1.2594 +  }
  1.2595 +
  1.2596 +  result = mgr->Clear();
  1.2597 +  if (NS_FAILED(result)) {
  1.2598 +    fail("Clear() failed. (%d)\n", result);
  1.2599 +    return result;
  1.2600 +  }
  1.2601 +
  1.2602 +  passed("Release the transaction manager");
  1.2603 +
  1.2604 +  /*******************************************************************
  1.2605 +   *
  1.2606 +   * Make sure number of transactions created matches number of
  1.2607 +   * transactions destroyed!
  1.2608 +   *
  1.2609 +   *******************************************************************/
  1.2610 +
  1.2611 +  /* Disabled because the current cycle collector doesn't delete
  1.2612 +     cycle collectable objects synchronously.
  1.2613 +  if (sConstructorCount != sDestructorCount) {
  1.2614 +    fail("Transaction constructor count (%d) != destructor count (%d).\n",
  1.2615 +         sConstructorCount, sDestructorCount);
  1.2616 +    return NS_ERROR_FAILURE;
  1.2617 +  }*/
  1.2618 +
  1.2619 +  passed("Number of transactions created and destroyed match");
  1.2620 +  passed("%d transactions processed during quick test", sConstructorCount);
  1.2621 +
  1.2622 +  return NS_OK;
  1.2623 +}
  1.2624 +
  1.2625 +nsresult
  1.2626 +simple_test()
  1.2627 +{
  1.2628 +  /*******************************************************************
  1.2629 +   *
  1.2630 +   * Initialize globals for test.
  1.2631 +   *
  1.2632 +   *******************************************************************/
  1.2633 +  reset_globals();
  1.2634 +  sDestructorOrderArr = sSimpleTestDestructorOrderArr;
  1.2635 +  sDoOrderArr         = sSimpleTestDoOrderArr;
  1.2636 +  sUndoOrderArr       = sSimpleTestUndoOrderArr;
  1.2637 +  sRedoOrderArr       = sSimpleTestRedoOrderArr;
  1.2638 +
  1.2639 +  /*******************************************************************
  1.2640 +   *
  1.2641 +   * Run the quick test.
  1.2642 +   *
  1.2643 +   *******************************************************************/
  1.2644 +
  1.2645 +  printf("\n-----------------------------------------------------\n");
  1.2646 +  printf("- Begin Simple Transaction Test:\n");
  1.2647 +  printf("-----------------------------------------------------\n");
  1.2648 +
  1.2649 +  SimpleTransactionFactory factory;
  1.2650 +
  1.2651 +  return quick_test(&factory);
  1.2652 +}
  1.2653 +
  1.2654 +nsresult
  1.2655 +aggregation_test()
  1.2656 +{
  1.2657 +  /*******************************************************************
  1.2658 +   *
  1.2659 +   * Initialize globals for test.
  1.2660 +   *
  1.2661 +   *******************************************************************/
  1.2662 +
  1.2663 +  reset_globals();
  1.2664 +  sDestructorOrderArr = sAggregateTestDestructorOrderArr;
  1.2665 +  sDoOrderArr         = sAggregateTestDoOrderArr;
  1.2666 +  sUndoOrderArr       = sAggregateTestUndoOrderArr;
  1.2667 +  sRedoOrderArr       = sAggregateTestRedoOrderArr;
  1.2668 +
  1.2669 +  /*******************************************************************
  1.2670 +   *
  1.2671 +   * Run the quick test.
  1.2672 +   *
  1.2673 +   *******************************************************************/
  1.2674 +
  1.2675 +  printf("\n-----------------------------------------------------\n");
  1.2676 +  printf("- Begin Aggregate Transaction Test:\n");
  1.2677 +  printf("-----------------------------------------------------\n");
  1.2678 +
  1.2679 +  AggregateTransactionFactory factory(3, 2);
  1.2680 +
  1.2681 +  return quick_test(&factory);
  1.2682 +}
  1.2683 +
  1.2684 +/**
  1.2685 + * Test behaviors in batch mode.
  1.2686 + **/
  1.2687 +nsresult
  1.2688 +quick_batch_test(TestTransactionFactory *factory)
  1.2689 +{
  1.2690 +  nsresult result;
  1.2691 +
  1.2692 +  /*******************************************************************
  1.2693 +   *
  1.2694 +   * Create a transaction manager implementation:
  1.2695 +   *
  1.2696 +   *******************************************************************/
  1.2697 +
  1.2698 +  nsCOMPtr<nsITransactionManager> mgr =
  1.2699 +    do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
  1.2700 +  if (NS_FAILED(result) || !mgr) {
  1.2701 +    fail("Failed to create Transaction Manager instance.\n");
  1.2702 +    return NS_ERROR_OUT_OF_MEMORY;
  1.2703 +  }
  1.2704 +
  1.2705 +  passed("Create transaction manager instance");
  1.2706 +
  1.2707 +  int32_t numitems;
  1.2708 +
  1.2709 +  /*******************************************************************
  1.2710 +   *
  1.2711 +   * Make sure an unbalanced call to EndBatch(false) with empty undo stack
  1.2712 +   * throws an error!
  1.2713 +   *
  1.2714 +   *******************************************************************/
  1.2715 +
  1.2716 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2717 +
  1.2718 +  if (NS_FAILED(result)) {
  1.2719 +    fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.2720 +         result);
  1.2721 +    return result;
  1.2722 +  }
  1.2723 +
  1.2724 +  if (numitems != 0) {
  1.2725 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.2726 +         numitems, result);
  1.2727 +    return NS_ERROR_FAILURE;
  1.2728 +  }
  1.2729 +
  1.2730 +  result = mgr->EndBatch(false);
  1.2731 +
  1.2732 +  if (result != NS_ERROR_FAILURE) {
  1.2733 +    fail("EndBatch(false) returned unexpected status. (%d)\n", result);
  1.2734 +    return result;
  1.2735 +  }
  1.2736 +
  1.2737 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2738 +
  1.2739 +  if (NS_FAILED(result)) {
  1.2740 +    fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.2741 +         result);
  1.2742 +    return result;
  1.2743 +  }
  1.2744 +
  1.2745 +  if (numitems != 0) {
  1.2746 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.2747 +         numitems, result);
  1.2748 +    return NS_ERROR_FAILURE;
  1.2749 +  }
  1.2750 +
  1.2751 +  passed("Test unbalanced EndBatch(false) with empty undo stack");
  1.2752 +
  1.2753 +  /*******************************************************************
  1.2754 +   *
  1.2755 +   * Make sure that an empty batch is not added to the undo stack
  1.2756 +   * when it is closed.
  1.2757 +   *
  1.2758 +   *******************************************************************/
  1.2759 +
  1.2760 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2761 +
  1.2762 +  if (NS_FAILED(result)) {
  1.2763 +    fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.2764 +         result);
  1.2765 +    return result;
  1.2766 +  }
  1.2767 +
  1.2768 +  if (numitems != 0) {
  1.2769 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.2770 +         numitems, result);
  1.2771 +    return NS_ERROR_FAILURE;
  1.2772 +  }
  1.2773 +
  1.2774 +  result = mgr->BeginBatch(nullptr);
  1.2775 +
  1.2776 +  if (NS_FAILED(result)) {
  1.2777 +    fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.2778 +    return result;
  1.2779 +  }
  1.2780 +
  1.2781 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2782 +
  1.2783 +  if (NS_FAILED(result)) {
  1.2784 +    fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.2785 +         result);
  1.2786 +    return result;
  1.2787 +  }
  1.2788 +
  1.2789 +  if (numitems != 0) {
  1.2790 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.2791 +         numitems, result);
  1.2792 +    return NS_ERROR_FAILURE;
  1.2793 +  }
  1.2794 +
  1.2795 +  result = mgr->EndBatch(false);
  1.2796 +
  1.2797 +  if (NS_FAILED(result)) {
  1.2798 +    fail("EndBatch(false) failed. (%d)\n", result);
  1.2799 +    return result;
  1.2800 +  }
  1.2801 +
  1.2802 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2803 +
  1.2804 +  if (NS_FAILED(result)) {
  1.2805 +    fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.2806 +         result);
  1.2807 +    return result;
  1.2808 +  }
  1.2809 +
  1.2810 +  if (numitems != 0) {
  1.2811 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.2812 +         numitems, result);
  1.2813 +    return NS_ERROR_FAILURE;
  1.2814 +  }
  1.2815 +
  1.2816 +  passed("Test empty batch");
  1.2817 +
  1.2818 +  int32_t i;
  1.2819 +  TestTransaction *tximpl;
  1.2820 +  nsITransaction *tx;
  1.2821 +
  1.2822 +  /*******************************************************************
  1.2823 +   *
  1.2824 +   * Execute 20 transactions. Afterwards, we should have 1
  1.2825 +   * transaction on the undo stack:
  1.2826 +   *
  1.2827 +   *******************************************************************/
  1.2828 +
  1.2829 +  result = mgr->BeginBatch(nullptr);
  1.2830 +
  1.2831 +  if (NS_FAILED(result)) {
  1.2832 +    fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.2833 +    return result;
  1.2834 +  }
  1.2835 +
  1.2836 +  for (i = 1; i <= 20; i++) {
  1.2837 +    tximpl = factory->create(mgr, NONE_FLAG);
  1.2838 +
  1.2839 +    if (!tximpl) {
  1.2840 +      fail("Failed to allocate transaction %d.\n", i);
  1.2841 +      return NS_ERROR_OUT_OF_MEMORY;
  1.2842 +    }
  1.2843 +
  1.2844 +    tx = 0;
  1.2845 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.2846 +    if (NS_FAILED(result)) {
  1.2847 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.2848 +           i, result);
  1.2849 +      return result;
  1.2850 +    }
  1.2851 +
  1.2852 +    result = mgr->DoTransaction(tx);
  1.2853 +    if (NS_FAILED(result)) {
  1.2854 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.2855 +      return result;
  1.2856 +    }
  1.2857 +
  1.2858 +    tx->Release();
  1.2859 +  }
  1.2860 +
  1.2861 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2862 +
  1.2863 +  if (NS_FAILED(result)) {
  1.2864 +    fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.2865 +         result);
  1.2866 +    return result;
  1.2867 +  }
  1.2868 +
  1.2869 +  if (numitems != 0) {
  1.2870 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.2871 +         numitems, result);
  1.2872 +    return NS_ERROR_FAILURE;
  1.2873 +  }
  1.2874 +
  1.2875 +  result = mgr->EndBatch(false);
  1.2876 +
  1.2877 +  if (NS_FAILED(result)) {
  1.2878 +    fail("EndBatch(false) failed. (%d)\n", result);
  1.2879 +    return result;
  1.2880 +  }
  1.2881 +
  1.2882 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2883 +
  1.2884 +  if (NS_FAILED(result)) {
  1.2885 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.2886 +         result);
  1.2887 +    return result;
  1.2888 +  }
  1.2889 +
  1.2890 +  if (numitems != 1) {
  1.2891 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.2892 +         numitems, result);
  1.2893 +    return NS_ERROR_FAILURE;
  1.2894 +  }
  1.2895 +
  1.2896 +  passed("Execute 20 batched transactions");
  1.2897 +
  1.2898 +  nsITransaction *u1, *u2;
  1.2899 +  nsITransaction *r1, *r2;
  1.2900 +
  1.2901 +  /*******************************************************************
  1.2902 +   *
  1.2903 +   * Execute 20 transient transactions. Afterwards, we should still
  1.2904 +   * have the same transaction on the undo stack:
  1.2905 +   *
  1.2906 +   *******************************************************************/
  1.2907 +
  1.2908 +  u1 = u2 = r1 = r2 = 0;
  1.2909 +
  1.2910 +  result = mgr->PeekUndoStack(&u1);
  1.2911 +
  1.2912 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.2913 +
  1.2914 +  if (NS_FAILED(result)) {
  1.2915 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.2916 +    return result;
  1.2917 +  }
  1.2918 +
  1.2919 +  result = mgr->PeekRedoStack(&r1);
  1.2920 +
  1.2921 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.2922 +
  1.2923 +  if (NS_FAILED(result)) {
  1.2924 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.2925 +    return result;
  1.2926 +  }
  1.2927 +
  1.2928 +  result = mgr->BeginBatch(nullptr);
  1.2929 +
  1.2930 +  if (NS_FAILED(result)) {
  1.2931 +    fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.2932 +    return result;
  1.2933 +  }
  1.2934 +
  1.2935 +  for (i = 1; i <= 20; i++) {
  1.2936 +    tximpl = factory->create(mgr, TRANSIENT_FLAG);
  1.2937 +
  1.2938 +    if (!tximpl) {
  1.2939 +      fail("Failed to allocate transaction %d.\n", i);
  1.2940 +      return NS_ERROR_OUT_OF_MEMORY;
  1.2941 +    }
  1.2942 +
  1.2943 +    tx = 0;
  1.2944 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.2945 +    if (NS_FAILED(result)) {
  1.2946 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.2947 +           i, result);
  1.2948 +      return result;
  1.2949 +    }
  1.2950 +
  1.2951 +    result = mgr->DoTransaction(tx);
  1.2952 +    if (NS_FAILED(result)) {
  1.2953 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.2954 +      return result;
  1.2955 +    }
  1.2956 +
  1.2957 +    tx->Release();
  1.2958 +  }
  1.2959 +
  1.2960 +  result = mgr->EndBatch(false);
  1.2961 +
  1.2962 +  if (NS_FAILED(result)) {
  1.2963 +    fail("EndBatch(false) failed. (%d)\n", result);
  1.2964 +    return result;
  1.2965 +  }
  1.2966 +
  1.2967 +  result = mgr->PeekUndoStack(&u2);
  1.2968 +
  1.2969 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.2970 +
  1.2971 +  if (NS_FAILED(result)) {
  1.2972 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.2973 +    return result;
  1.2974 +  }
  1.2975 +
  1.2976 +  if (u1 != u2) {
  1.2977 +    fail("Top of undo stack changed. (%d)\n", result);
  1.2978 +    return NS_ERROR_FAILURE;
  1.2979 +  }
  1.2980 +
  1.2981 +  result = mgr->PeekRedoStack(&r2);
  1.2982 +
  1.2983 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.2984 +
  1.2985 +  if (NS_FAILED(result)) {
  1.2986 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.2987 +    return result;
  1.2988 +  }
  1.2989 +
  1.2990 +  if (r1 != r2) {
  1.2991 +    fail("Top of redo stack changed. (%d)\n", result);
  1.2992 +    return NS_ERROR_FAILURE;
  1.2993 +  }
  1.2994 +
  1.2995 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.2996 +
  1.2997 +  if (NS_FAILED(result)) {
  1.2998 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.2999 +         result);
  1.3000 +    return result;
  1.3001 +  }
  1.3002 +
  1.3003 +  if (numitems != 1) {
  1.3004 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.3005 +         numitems, result);
  1.3006 +    return NS_ERROR_FAILURE;
  1.3007 +  }
  1.3008 +
  1.3009 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3010 +
  1.3011 +  if (NS_FAILED(result)) {
  1.3012 +    fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.3013 +         result);
  1.3014 +    return result;
  1.3015 +  }
  1.3016 +
  1.3017 +  if (numitems != 0) {
  1.3018 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.3019 +         numitems, result);
  1.3020 +    return NS_ERROR_FAILURE;
  1.3021 +  }
  1.3022 +
  1.3023 +  passed("Execute 20 batched transient transactions");
  1.3024 +
  1.3025 +  /*******************************************************************
  1.3026 +   *
  1.3027 +   * Test nested batching. Afterwards, we should have 2 transactions
  1.3028 +   * on the undo stack:
  1.3029 +   *
  1.3030 +   *******************************************************************/
  1.3031 +
  1.3032 +  result = mgr->BeginBatch(nullptr);
  1.3033 +
  1.3034 +  if (NS_FAILED(result)) {
  1.3035 +    fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.3036 +    return result;
  1.3037 +  }
  1.3038 +
  1.3039 +  tximpl = factory->create(mgr, NONE_FLAG);
  1.3040 +
  1.3041 +  if (!tximpl) {
  1.3042 +    fail("Failed to allocate transaction.\n");
  1.3043 +    return NS_ERROR_OUT_OF_MEMORY;
  1.3044 +  }
  1.3045 +
  1.3046 +  tx = 0;
  1.3047 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.3048 +  if (NS_FAILED(result)) {
  1.3049 +    fail("QueryInterface() failed for transaction. (%d)\n", result);
  1.3050 +    return result;
  1.3051 +  }
  1.3052 +
  1.3053 +  result = mgr->DoTransaction(tx);
  1.3054 +  if (NS_FAILED(result)) {
  1.3055 +    fail("Failed to execute transaction. (%d)\n", result);
  1.3056 +    return result;
  1.3057 +  }
  1.3058 +
  1.3059 +  tx->Release();
  1.3060 +
  1.3061 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3062 +
  1.3063 +  if (NS_FAILED(result)) {
  1.3064 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.3065 +         result);
  1.3066 +    return result;
  1.3067 +  }
  1.3068 +
  1.3069 +  if (numitems != 1) {
  1.3070 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.3071 +         numitems, result);
  1.3072 +    return NS_ERROR_FAILURE;
  1.3073 +  }
  1.3074 +
  1.3075 +  result = mgr->BeginBatch(nullptr);
  1.3076 +
  1.3077 +  if (NS_FAILED(result)) {
  1.3078 +    fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.3079 +    return result;
  1.3080 +  }
  1.3081 +
  1.3082 +  tximpl = factory->create(mgr, NONE_FLAG);
  1.3083 +
  1.3084 +  if (!tximpl) {
  1.3085 +    fail("Failed to allocate transaction.\n");
  1.3086 +    return NS_ERROR_OUT_OF_MEMORY;
  1.3087 +  }
  1.3088 +
  1.3089 +  tx = 0;
  1.3090 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.3091 +  if (NS_FAILED(result)) {
  1.3092 +    fail("QueryInterface() failed for transaction. (%d)\n", result);
  1.3093 +    return result;
  1.3094 +  }
  1.3095 +
  1.3096 +  result = mgr->DoTransaction(tx);
  1.3097 +  if (NS_FAILED(result)) {
  1.3098 +    fail("Failed to execute transaction. (%d)\n", result);
  1.3099 +    return result;
  1.3100 +  }
  1.3101 +
  1.3102 +  tx->Release();
  1.3103 +
  1.3104 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3105 +
  1.3106 +  if (NS_FAILED(result)) {
  1.3107 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.3108 +         result);
  1.3109 +    return result;
  1.3110 +  }
  1.3111 +
  1.3112 +  if (numitems != 1) {
  1.3113 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.3114 +         numitems, result);
  1.3115 +    return NS_ERROR_FAILURE;
  1.3116 +  }
  1.3117 +
  1.3118 +  result = mgr->BeginBatch(nullptr);
  1.3119 +
  1.3120 +  if (NS_FAILED(result)) {
  1.3121 +    fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.3122 +    return result;
  1.3123 +  }
  1.3124 +
  1.3125 +  tximpl = factory->create(mgr, NONE_FLAG);
  1.3126 +
  1.3127 +  if (!tximpl) {
  1.3128 +    fail("Failed to allocate transaction.\n");
  1.3129 +    return NS_ERROR_OUT_OF_MEMORY;
  1.3130 +  }
  1.3131 +
  1.3132 +  tx = 0;
  1.3133 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.3134 +  if (NS_FAILED(result)) {
  1.3135 +    fail("QueryInterface() failed for transaction. (%d)\n", result);
  1.3136 +    return result;
  1.3137 +  }
  1.3138 +
  1.3139 +  result = mgr->DoTransaction(tx);
  1.3140 +  if (NS_FAILED(result)) {
  1.3141 +    fail("Failed to execute transaction. (%d)\n", result);
  1.3142 +    return result;
  1.3143 +  }
  1.3144 +
  1.3145 +  tx->Release();
  1.3146 +
  1.3147 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3148 +
  1.3149 +  if (NS_FAILED(result)) {
  1.3150 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.3151 +         result);
  1.3152 +    return result;
  1.3153 +  }
  1.3154 +
  1.3155 +  if (numitems != 1) {
  1.3156 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.3157 +         numitems, result);
  1.3158 +    return NS_ERROR_FAILURE;
  1.3159 +  }
  1.3160 +
  1.3161 +  result = mgr->EndBatch(false);
  1.3162 +
  1.3163 +  if (NS_FAILED(result)) {
  1.3164 +    fail("EndBatch(false) failed. (%d)\n", result);
  1.3165 +    return result;
  1.3166 +  }
  1.3167 +
  1.3168 +  result = mgr->EndBatch(false);
  1.3169 +
  1.3170 +  if (NS_FAILED(result)) {
  1.3171 +    fail("EndBatch(false) failed. (%d)\n", result);
  1.3172 +    return result;
  1.3173 +  }
  1.3174 +
  1.3175 +  result = mgr->EndBatch(false);
  1.3176 +
  1.3177 +  if (NS_FAILED(result)) {
  1.3178 +    fail("EndBatch(false) failed. (%d)\n", result);
  1.3179 +    return result;
  1.3180 +  }
  1.3181 +
  1.3182 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3183 +
  1.3184 +  if (NS_FAILED(result)) {
  1.3185 +    fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
  1.3186 +         result);
  1.3187 +    return result;
  1.3188 +  }
  1.3189 +
  1.3190 +  if (numitems != 2) {
  1.3191 +    fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
  1.3192 +         numitems, result);
  1.3193 +    return NS_ERROR_FAILURE;
  1.3194 +  }
  1.3195 +
  1.3196 +  passed("Test nested batched transactions");
  1.3197 +
  1.3198 +  /*******************************************************************
  1.3199 +   *
  1.3200 +   * Undo 2 batch transactions. Afterwards, we should have 0
  1.3201 +   * transactions on the undo stack and 2 on the redo stack.
  1.3202 +   *
  1.3203 +   *******************************************************************/
  1.3204 +
  1.3205 +  for (i = 1; i <= 2; ++i) {
  1.3206 +    result = mgr->UndoTransaction();
  1.3207 +    if (NS_FAILED(result)) {
  1.3208 +      fail("Failed to undo transaction %d. (%d)\n", i, result);
  1.3209 +      return result;
  1.3210 +    }
  1.3211 +  }
  1.3212 +
  1.3213 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3214 +
  1.3215 +  if (NS_FAILED(result)) {
  1.3216 +    fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.3217 +         result);
  1.3218 +    return result;
  1.3219 +  }
  1.3220 +
  1.3221 +  if (numitems != 0) {
  1.3222 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.3223 +         numitems, result);
  1.3224 +    return NS_ERROR_FAILURE;
  1.3225 +  }
  1.3226 +
  1.3227 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3228 +
  1.3229 +  if (NS_FAILED(result)) {
  1.3230 +    fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
  1.3231 +         result);
  1.3232 +    return result;
  1.3233 +  }
  1.3234 +
  1.3235 +  if (numitems != 2) {
  1.3236 +    fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
  1.3237 +         numitems, result);
  1.3238 +    return NS_ERROR_FAILURE;
  1.3239 +  }
  1.3240 +
  1.3241 +  passed("Undo 2 batch transactions");
  1.3242 +
  1.3243 +  /*******************************************************************
  1.3244 +   *
  1.3245 +   * Redo 2 batch transactions. Afterwards, we should have 2
  1.3246 +   * transactions on the undo stack and 0 on the redo stack.
  1.3247 +   *
  1.3248 +   *******************************************************************/
  1.3249 +
  1.3250 +  for (i = 1; i <= 2; ++i) {
  1.3251 +    result = mgr->RedoTransaction();
  1.3252 +    if (NS_FAILED(result)) {
  1.3253 +      fail("Failed to undo transaction %d. (%d)\n", i, result);
  1.3254 +      return result;
  1.3255 +    }
  1.3256 +  }
  1.3257 +
  1.3258 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3259 +
  1.3260 +  if (NS_FAILED(result)) {
  1.3261 +    fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
  1.3262 +         result);
  1.3263 +    return result;
  1.3264 +  }
  1.3265 +
  1.3266 +  if (numitems != 2) {
  1.3267 +    fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
  1.3268 +         numitems, result);
  1.3269 +    return NS_ERROR_FAILURE;
  1.3270 +  }
  1.3271 +
  1.3272 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3273 +
  1.3274 +  if (NS_FAILED(result)) {
  1.3275 +    fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.3276 +         result);
  1.3277 +    return result;
  1.3278 +  }
  1.3279 +
  1.3280 +  if (numitems != 0) {
  1.3281 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.3282 +         numitems, result);
  1.3283 +    return NS_ERROR_FAILURE;
  1.3284 +  }
  1.3285 +
  1.3286 +  passed("Redo 2 batch transactions");
  1.3287 +
  1.3288 +  /*******************************************************************
  1.3289 +   *
  1.3290 +   * Call undo. Afterwards, we should have 1 transaction
  1.3291 +   * on the undo stack, and 1 on the redo stack:
  1.3292 +   *
  1.3293 +   *******************************************************************/
  1.3294 +
  1.3295 +  result = mgr->UndoTransaction();
  1.3296 +
  1.3297 +  if (NS_FAILED(result)) {
  1.3298 +    fail("Failed to undo transaction. (%d)\n", result);
  1.3299 +    return result;
  1.3300 +  }
  1.3301 +
  1.3302 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3303 +
  1.3304 +  if (NS_FAILED(result)) {
  1.3305 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.3306 +         result);
  1.3307 +    return result;
  1.3308 +  }
  1.3309 +
  1.3310 +  if (numitems != 1) {
  1.3311 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.3312 +         numitems, result);
  1.3313 +    return NS_ERROR_FAILURE;
  1.3314 +  }
  1.3315 +
  1.3316 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3317 +
  1.3318 +  if (NS_FAILED(result)) {
  1.3319 +    fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
  1.3320 +         result);
  1.3321 +    return result;
  1.3322 +  }
  1.3323 +
  1.3324 +  if (numitems != 1) {
  1.3325 +    fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  1.3326 +         numitems, result);
  1.3327 +    return NS_ERROR_FAILURE;
  1.3328 +  }
  1.3329 +
  1.3330 +  passed("Undo a batched transaction that was redone");
  1.3331 +
  1.3332 +  /*******************************************************************
  1.3333 +   *
  1.3334 +   * Make sure an unbalanced call to EndBatch(false) throws an error and
  1.3335 +   * doesn't affect the undo and redo stacks!
  1.3336 +   *
  1.3337 +   *******************************************************************/
  1.3338 +
  1.3339 +  result = mgr->EndBatch(false);
  1.3340 +
  1.3341 +  if (result != NS_ERROR_FAILURE) {
  1.3342 +    fail("EndBatch(false) returned unexpected status. (%d)\n", result);
  1.3343 +    return result;
  1.3344 +  }
  1.3345 +
  1.3346 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3347 +
  1.3348 +  if (NS_FAILED(result)) {
  1.3349 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.3350 +         result);
  1.3351 +    return result;
  1.3352 +  }
  1.3353 +
  1.3354 +  if (numitems != 1) {
  1.3355 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.3356 +         numitems, result);
  1.3357 +    return NS_ERROR_FAILURE;
  1.3358 +  }
  1.3359 +
  1.3360 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3361 +
  1.3362 +  if (NS_FAILED(result)) {
  1.3363 +    fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
  1.3364 +         result);
  1.3365 +    return result;
  1.3366 +  }
  1.3367 +
  1.3368 +  if (numitems != 1) {
  1.3369 +    fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  1.3370 +         numitems, result);
  1.3371 +    return NS_ERROR_FAILURE;
  1.3372 +  }
  1.3373 +
  1.3374 +  passed("Test effect of unbalanced EndBatch(false) on undo and redo stacks");
  1.3375 +
  1.3376 +  /*******************************************************************
  1.3377 +   *
  1.3378 +   * Make sure that an empty batch is not added to the undo stack
  1.3379 +   * when it is closed, and that it does not affect the undo and redo
  1.3380 +   * stacks.
  1.3381 +   *
  1.3382 +   *******************************************************************/
  1.3383 +
  1.3384 +  result = mgr->BeginBatch(nullptr);
  1.3385 +
  1.3386 +  if (NS_FAILED(result)) {
  1.3387 +    fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.3388 +    return result;
  1.3389 +  }
  1.3390 +
  1.3391 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3392 +
  1.3393 +  if (NS_FAILED(result)) {
  1.3394 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.3395 +         result);
  1.3396 +    return result;
  1.3397 +  }
  1.3398 +
  1.3399 +  if (numitems != 1) {
  1.3400 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.3401 +         numitems, result);
  1.3402 +    return NS_ERROR_FAILURE;
  1.3403 +  }
  1.3404 +
  1.3405 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3406 +
  1.3407 +  if (NS_FAILED(result)) {
  1.3408 +    fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
  1.3409 +         result);
  1.3410 +    return result;
  1.3411 +  }
  1.3412 +
  1.3413 +  if (numitems != 1) {
  1.3414 +    fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  1.3415 +         numitems, result);
  1.3416 +    return NS_ERROR_FAILURE;
  1.3417 +  }
  1.3418 +
  1.3419 +  result = mgr->EndBatch(false);
  1.3420 +
  1.3421 +  if (NS_FAILED(result)) {
  1.3422 +    fail("EndBatch(false) failed. (%d)\n", result);
  1.3423 +    return result;
  1.3424 +  }
  1.3425 +
  1.3426 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3427 +
  1.3428 +  if (NS_FAILED(result)) {
  1.3429 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.3430 +         result);
  1.3431 +    return result;
  1.3432 +  }
  1.3433 +
  1.3434 +  if (numitems != 1) {
  1.3435 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.3436 +         numitems, result);
  1.3437 +    return NS_ERROR_FAILURE;
  1.3438 +  }
  1.3439 +
  1.3440 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3441 +
  1.3442 +  if (NS_FAILED(result)) {
  1.3443 +    fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
  1.3444 +         result);
  1.3445 +    return result;
  1.3446 +  }
  1.3447 +
  1.3448 +  if (numitems != 1) {
  1.3449 +    fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  1.3450 +         numitems, result);
  1.3451 +    return NS_ERROR_FAILURE;
  1.3452 +  }
  1.3453 +
  1.3454 +  passed("Test effect of empty batch on undo and redo stacks");
  1.3455 +
  1.3456 +  /*******************************************************************
  1.3457 +   *
  1.3458 +   * Execute a new transaction. The redo stack should get pruned!
  1.3459 +   *
  1.3460 +   *******************************************************************/
  1.3461 +
  1.3462 +  result = mgr->BeginBatch(nullptr);
  1.3463 +
  1.3464 +  if (NS_FAILED(result)) {
  1.3465 +    fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.3466 +    return result;
  1.3467 +  }
  1.3468 +
  1.3469 +  for (i = 1; i <= 20; i++) {
  1.3470 +    tximpl = factory->create(mgr, NONE_FLAG);
  1.3471 +
  1.3472 +    if (!tximpl) {
  1.3473 +      fail("Failed to allocate transaction %d.\n", i);
  1.3474 +      return NS_ERROR_OUT_OF_MEMORY;
  1.3475 +    }
  1.3476 +
  1.3477 +    tx = 0;
  1.3478 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.3479 +    if (NS_FAILED(result)) {
  1.3480 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.3481 +           i, result);
  1.3482 +      return result;
  1.3483 +    }
  1.3484 +
  1.3485 +    result = mgr->DoTransaction(tx);
  1.3486 +    if (NS_FAILED(result)) {
  1.3487 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.3488 +      return result;
  1.3489 +    }
  1.3490 +
  1.3491 +    tx->Release();
  1.3492 +  }
  1.3493 +
  1.3494 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3495 +
  1.3496 +  if (NS_FAILED(result)) {
  1.3497 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.3498 +         result);
  1.3499 +    return result;
  1.3500 +  }
  1.3501 +
  1.3502 +  if (numitems != 1) {
  1.3503 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.3504 +         numitems, result);
  1.3505 +    return NS_ERROR_FAILURE;
  1.3506 +  }
  1.3507 +
  1.3508 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3509 +
  1.3510 +  if (NS_FAILED(result)) {
  1.3511 +    fail("GetNumberOfRedoItems() on redo stack with 1 item failed. (%d)\n",
  1.3512 +         result);
  1.3513 +    return result;
  1.3514 +  }
  1.3515 +
  1.3516 +  if (numitems != 1) {
  1.3517 +    fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  1.3518 +         numitems, result);
  1.3519 +    return NS_ERROR_FAILURE;
  1.3520 +  }
  1.3521 +
  1.3522 +  result = mgr->EndBatch(false);
  1.3523 +
  1.3524 +  if (NS_FAILED(result)) {
  1.3525 +    fail("EndBatch(false) failed. (%d)\n", result);
  1.3526 +    return result;
  1.3527 +  }
  1.3528 +
  1.3529 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3530 +
  1.3531 +  if (NS_FAILED(result)) {
  1.3532 +    fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
  1.3533 +         result);
  1.3534 +    return result;
  1.3535 +  }
  1.3536 +
  1.3537 +  if (numitems != 2) {
  1.3538 +    fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
  1.3539 +         numitems, result);
  1.3540 +    return NS_ERROR_FAILURE;
  1.3541 +  }
  1.3542 +
  1.3543 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3544 +
  1.3545 +  if (NS_FAILED(result)) {
  1.3546 +    fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.3547 +         result);
  1.3548 +    return result;
  1.3549 +  }
  1.3550 +
  1.3551 +  if (numitems != 0) {
  1.3552 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.3553 +         numitems, result);
  1.3554 +    return NS_ERROR_FAILURE;
  1.3555 +  }
  1.3556 +
  1.3557 +  passed("Check if new batched transactions prune the redo stack");
  1.3558 +
  1.3559 +  /*******************************************************************
  1.3560 +   *
  1.3561 +   * Call undo.
  1.3562 +   *
  1.3563 +   *******************************************************************/
  1.3564 +
  1.3565 +  // Move a transaction over to the redo stack, so that we have one
  1.3566 +  // transaction on the undo stack, and one on the redo stack!
  1.3567 +
  1.3568 +  result = mgr->UndoTransaction();
  1.3569 +
  1.3570 +  if (NS_FAILED(result)) {
  1.3571 +    fail("Failed to undo transaction. (%d)\n", result);
  1.3572 +    return result;
  1.3573 +  }
  1.3574 +
  1.3575 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3576 +
  1.3577 +  if (NS_FAILED(result)) {
  1.3578 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.3579 +         result);
  1.3580 +    return result;
  1.3581 +  }
  1.3582 +
  1.3583 +  if (numitems != 1) {
  1.3584 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.3585 +         numitems, result);
  1.3586 +    return NS_ERROR_FAILURE;
  1.3587 +  }
  1.3588 +
  1.3589 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3590 +
  1.3591 +  if (NS_FAILED(result)) {
  1.3592 +    fail("GetNumberOfRedoItems() on redo stack with 1 item failed. (%d)\n",
  1.3593 +         result);
  1.3594 +    return result;
  1.3595 +  }
  1.3596 +
  1.3597 +  if (numitems != 1) {
  1.3598 +    fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  1.3599 +         numitems, result);
  1.3600 +    return NS_ERROR_FAILURE;
  1.3601 +  }
  1.3602 +
  1.3603 +  passed("Call undo");
  1.3604 +
  1.3605 +  /*******************************************************************
  1.3606 +   *
  1.3607 +   * Test transaction DoTransaction() error:
  1.3608 +   *
  1.3609 +   *******************************************************************/
  1.3610 +
  1.3611 +  tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
  1.3612 +
  1.3613 +  if (!tximpl) {
  1.3614 +    fail("Failed to allocate transaction.\n");
  1.3615 +    return NS_ERROR_OUT_OF_MEMORY;
  1.3616 +  }
  1.3617 +
  1.3618 +  tx     = 0;
  1.3619 +
  1.3620 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.3621 +
  1.3622 +  if (NS_FAILED(result)) {
  1.3623 +    fail("QueryInterface() failed for transaction. (%d)\n", result);
  1.3624 +    return result;
  1.3625 +  }
  1.3626 +
  1.3627 +  u1 = u2 = r1 = r2 = 0;
  1.3628 +
  1.3629 +  result = mgr->PeekUndoStack(&u1);
  1.3630 +
  1.3631 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.3632 +
  1.3633 +  if (NS_FAILED(result)) {
  1.3634 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.3635 +    return result;
  1.3636 +  }
  1.3637 +
  1.3638 +  result = mgr->PeekRedoStack(&r1);
  1.3639 +
  1.3640 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.3641 +
  1.3642 +  if (NS_FAILED(result)) {
  1.3643 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.3644 +    return result;
  1.3645 +  }
  1.3646 +
  1.3647 +  result = mgr->BeginBatch(nullptr);
  1.3648 +
  1.3649 +  if (NS_FAILED(result)) {
  1.3650 +    fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.3651 +    return result;
  1.3652 +  }
  1.3653 +
  1.3654 +  result = mgr->DoTransaction(tx);
  1.3655 +
  1.3656 +  if (result != NS_ERROR_FAILURE) {
  1.3657 +    fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1.3658 +    return result;
  1.3659 +  }
  1.3660 +
  1.3661 +  tx->Release();
  1.3662 +
  1.3663 +  result = mgr->EndBatch(false);
  1.3664 +
  1.3665 +  if (NS_FAILED(result)) {
  1.3666 +    fail("EndBatch(false) failed. (%d)\n", result);
  1.3667 +    return result;
  1.3668 +  }
  1.3669 +
  1.3670 +  result = mgr->PeekUndoStack(&u2);
  1.3671 +
  1.3672 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.3673 +
  1.3674 +  if (NS_FAILED(result)) {
  1.3675 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.3676 +    return result;
  1.3677 +  }
  1.3678 +
  1.3679 +  if (u1 != u2) {
  1.3680 +    fail("Top of undo stack changed. (%d)\n", result);
  1.3681 +    return NS_ERROR_FAILURE;
  1.3682 +  }
  1.3683 +
  1.3684 +  result = mgr->PeekRedoStack(&r2);
  1.3685 +
  1.3686 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.3687 +
  1.3688 +  if (NS_FAILED(result)) {
  1.3689 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.3690 +    return result;
  1.3691 +  }
  1.3692 +
  1.3693 +  if (r1 != r2) {
  1.3694 +    fail("Top of redo stack changed. (%d)\n", result);
  1.3695 +    return NS_ERROR_FAILURE;
  1.3696 +  }
  1.3697 +
  1.3698 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3699 +
  1.3700 +  if (NS_FAILED(result)) {
  1.3701 +    fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1.3702 +         result);
  1.3703 +    return result;
  1.3704 +  }
  1.3705 +
  1.3706 +  if (numitems != 1) {
  1.3707 +    fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1.3708 +         numitems, result);
  1.3709 +    return NS_ERROR_FAILURE;
  1.3710 +  }
  1.3711 +
  1.3712 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3713 +
  1.3714 +  if (NS_FAILED(result)) {
  1.3715 +    fail("GetNumberOfRedoItems() on redo stack with 1 item failed. (%d)\n",
  1.3716 +         result);
  1.3717 +    return result;
  1.3718 +  }
  1.3719 +
  1.3720 +  if (numitems != 1) {
  1.3721 +    fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  1.3722 +         numitems, result);
  1.3723 +    return NS_ERROR_FAILURE;
  1.3724 +  }
  1.3725 +
  1.3726 +  passed("Test transaction DoTransaction() error");
  1.3727 +
  1.3728 +  /*******************************************************************
  1.3729 +   *
  1.3730 +   * Test transaction UndoTransaction() error:
  1.3731 +   *
  1.3732 +   *******************************************************************/
  1.3733 +
  1.3734 +  tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
  1.3735 +
  1.3736 +  if (!tximpl) {
  1.3737 +    fail("Failed to allocate transaction.\n");
  1.3738 +    return NS_ERROR_OUT_OF_MEMORY;
  1.3739 +  }
  1.3740 +
  1.3741 +  tx     = 0;
  1.3742 +
  1.3743 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.3744 +
  1.3745 +  if (NS_FAILED(result)) {
  1.3746 +    fail("QueryInterface() failed for transaction. (%d)\n", result);
  1.3747 +    return result;
  1.3748 +  }
  1.3749 +
  1.3750 +  result = mgr->BeginBatch(nullptr);
  1.3751 +
  1.3752 +  if (NS_FAILED(result)) {
  1.3753 +    fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.3754 +    return result;
  1.3755 +  }
  1.3756 +
  1.3757 +  result = mgr->DoTransaction(tx);
  1.3758 +
  1.3759 +  if (NS_FAILED(result)) {
  1.3760 +    fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1.3761 +    return result;
  1.3762 +  }
  1.3763 +
  1.3764 +  tx->Release();
  1.3765 +
  1.3766 +  result = mgr->EndBatch(false);
  1.3767 +
  1.3768 +  if (NS_FAILED(result)) {
  1.3769 +    fail("EndBatch(false) failed. (%d)\n", result);
  1.3770 +    return result;
  1.3771 +  }
  1.3772 +
  1.3773 +  u1 = u2 = r1 = r2 = 0;
  1.3774 +
  1.3775 +  result = mgr->PeekUndoStack(&u1);
  1.3776 +
  1.3777 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.3778 +
  1.3779 +  if (NS_FAILED(result)) {
  1.3780 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.3781 +    return result;
  1.3782 +  }
  1.3783 +
  1.3784 +  result = mgr->PeekRedoStack(&r1);
  1.3785 +
  1.3786 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.3787 +
  1.3788 +  if (NS_FAILED(result)) {
  1.3789 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.3790 +    return result;
  1.3791 +  }
  1.3792 +
  1.3793 +  result = mgr->UndoTransaction();
  1.3794 +
  1.3795 +  if (result != NS_ERROR_FAILURE) {
  1.3796 +    fail("UndoTransaction() returned unexpected error. (%d)\n", result);
  1.3797 +    return result;
  1.3798 +  }
  1.3799 +
  1.3800 +  result = mgr->PeekUndoStack(&u2);
  1.3801 +
  1.3802 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.3803 +
  1.3804 +  if (NS_FAILED(result)) {
  1.3805 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.3806 +    return result;
  1.3807 +  }
  1.3808 +
  1.3809 +  if (u1 != u2) {
  1.3810 +    fail("Top of undo stack changed. (%d)\n", result);
  1.3811 +    return NS_ERROR_FAILURE;
  1.3812 +  }
  1.3813 +
  1.3814 +  result = mgr->PeekRedoStack(&r2);
  1.3815 +
  1.3816 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.3817 +
  1.3818 +  if (NS_FAILED(result)) {
  1.3819 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.3820 +    return result;
  1.3821 +  }
  1.3822 +
  1.3823 +  if (r1 != r2) {
  1.3824 +    fail("Top of redo stack changed. (%d)\n", result);
  1.3825 +    return NS_ERROR_FAILURE;
  1.3826 +  }
  1.3827 +
  1.3828 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.3829 +
  1.3830 +  if (NS_FAILED(result)) {
  1.3831 +    fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
  1.3832 +         result);
  1.3833 +    return result;
  1.3834 +  }
  1.3835 +
  1.3836 +  if (numitems != 2) {
  1.3837 +    fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
  1.3838 +         numitems, result);
  1.3839 +    return NS_ERROR_FAILURE;
  1.3840 +  }
  1.3841 +
  1.3842 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.3843 +
  1.3844 +  if (NS_FAILED(result)) {
  1.3845 +    fail("GetNumberOfRedoItems() on empty redo stack. (%d)\n",
  1.3846 +         result);
  1.3847 +    return result;
  1.3848 +  }
  1.3849 +
  1.3850 +  if (numitems != 0) {
  1.3851 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.3852 +         numitems, result);
  1.3853 +    return NS_ERROR_FAILURE;
  1.3854 +  }
  1.3855 +
  1.3856 +  passed("Test transaction UndoTransaction() error");
  1.3857 +
  1.3858 +  /*******************************************************************
  1.3859 +   *
  1.3860 +   * Test transaction RedoTransaction() error:
  1.3861 +   *
  1.3862 +   *******************************************************************/
  1.3863 +
  1.3864 +  tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
  1.3865 +
  1.3866 +  if (!tximpl) {
  1.3867 +    fail("Failed to allocate transaction.\n");
  1.3868 +    return NS_ERROR_OUT_OF_MEMORY;
  1.3869 +  }
  1.3870 +
  1.3871 +  tx     = 0;
  1.3872 +
  1.3873 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.3874 +
  1.3875 +  if (NS_FAILED(result)) {
  1.3876 +    fail("QueryInterface() failed for RedoErrorTransaction. (%d)\n",
  1.3877 +         result);
  1.3878 +    return result;
  1.3879 +  }
  1.3880 +
  1.3881 +  result = mgr->BeginBatch(nullptr);
  1.3882 +
  1.3883 +  if (NS_FAILED(result)) {
  1.3884 +    fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.3885 +    return result;
  1.3886 +  }
  1.3887 +
  1.3888 +  result = mgr->DoTransaction(tx);
  1.3889 +
  1.3890 +  if (NS_FAILED(result)) {
  1.3891 +    fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1.3892 +    return result;
  1.3893 +  }
  1.3894 +
  1.3895 +  tx->Release();
  1.3896 +
  1.3897 +  result = mgr->EndBatch(false);
  1.3898 +
  1.3899 +  if (NS_FAILED(result)) {
  1.3900 +    fail("EndBatch(false) failed. (%d)\n", result);
  1.3901 +    return result;
  1.3902 +  }
  1.3903 +
  1.3904 +  //
  1.3905 +  // Execute a normal transaction to be used in a later test:
  1.3906 +  //
  1.3907 +
  1.3908 +  tximpl = factory->create(mgr, NONE_FLAG);
  1.3909 +
  1.3910 +  if (!tximpl) {
  1.3911 +    fail("Failed to allocate transaction.\n");
  1.3912 +    return NS_ERROR_OUT_OF_MEMORY;
  1.3913 +  }
  1.3914 +
  1.3915 +  tx     = 0;
  1.3916 +
  1.3917 +  result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.3918 +
  1.3919 +  if (NS_FAILED(result)) {
  1.3920 +    fail("QueryInterface() failed for transaction. (%d)\n", result);
  1.3921 +    return result;
  1.3922 +  }
  1.3923 +
  1.3924 +  result = mgr->DoTransaction(tx);
  1.3925 +
  1.3926 +  if (NS_FAILED(result)) {
  1.3927 +    fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1.3928 +    return result;
  1.3929 +  }
  1.3930 +
  1.3931 +  tx->Release();
  1.3932 +
  1.3933 +  //
  1.3934 +  // Undo the 2 transactions just executed.
  1.3935 +  //
  1.3936 +
  1.3937 +  for (i = 1; i <= 2; ++i) {
  1.3938 +    result = mgr->UndoTransaction();
  1.3939 +    if (NS_FAILED(result)) {
  1.3940 +      fail("Failed to undo transaction %d. (%d)\n", i, result);
  1.3941 +      return result;
  1.3942 +    }
  1.3943 +  }
  1.3944 +
  1.3945 +  //
  1.3946 +  // The RedoErrorTransaction should now be at the top of the redo stack!
  1.3947 +  //
  1.3948 +
  1.3949 +  u1 = u2 = r1 = r2 = 0;
  1.3950 +
  1.3951 +  result = mgr->PeekUndoStack(&u1);
  1.3952 +
  1.3953 +  TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1.3954 +
  1.3955 +  if (NS_FAILED(result)) {
  1.3956 +    fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1.3957 +    return result;
  1.3958 +  }
  1.3959 +
  1.3960 +  result = mgr->PeekRedoStack(&r1);
  1.3961 +
  1.3962 +  TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1.3963 +
  1.3964 +  if (NS_FAILED(result)) {
  1.3965 +    fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1.3966 +    return result;
  1.3967 +  }
  1.3968 +
  1.3969 +  result = mgr->RedoTransaction();
  1.3970 +
  1.3971 +  if (result != NS_ERROR_FAILURE) {
  1.3972 +    fail("RedoTransaction() returned unexpected error. (%d)\n", result);
  1.3973 +    return result;
  1.3974 +  }
  1.3975 +
  1.3976 +  result = mgr->PeekUndoStack(&u2);
  1.3977 +
  1.3978 +  TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1.3979 +
  1.3980 +  if (NS_FAILED(result)) {
  1.3981 +    fail("Second PeekUndoStack() failed. (%d)\n", result);
  1.3982 +    return result;
  1.3983 +  }
  1.3984 +
  1.3985 +  if (u1 != u2) {
  1.3986 +    fail("Top of undo stack changed. (%d)\n", result);
  1.3987 +    return NS_ERROR_FAILURE;
  1.3988 +  }
  1.3989 +
  1.3990 +  result = mgr->PeekRedoStack(&r2);
  1.3991 +
  1.3992 +  TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1.3993 +
  1.3994 +  if (NS_FAILED(result)) {
  1.3995 +    fail("Second PeekRedoStack() failed. (%d)\n", result);
  1.3996 +    return result;
  1.3997 +  }
  1.3998 +
  1.3999 +  if (r1 != r2) {
  1.4000 +    fail("Top of redo stack changed. (%d)\n", result);
  1.4001 +    return NS_ERROR_FAILURE;
  1.4002 +  }
  1.4003 +
  1.4004 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.4005 +
  1.4006 +  if (NS_FAILED(result)) {
  1.4007 +    fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
  1.4008 +         result);
  1.4009 +    return result;
  1.4010 +  }
  1.4011 +
  1.4012 +  if (numitems != 2) {
  1.4013 +    fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
  1.4014 +         numitems, result);
  1.4015 +    return NS_ERROR_FAILURE;
  1.4016 +  }
  1.4017 +
  1.4018 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.4019 +
  1.4020 +  if (NS_FAILED(result)) {
  1.4021 +    fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
  1.4022 +         result);
  1.4023 +    return result;
  1.4024 +  }
  1.4025 +
  1.4026 +  if (numitems != 2) {
  1.4027 +    fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
  1.4028 +         numitems, result);
  1.4029 +    return NS_ERROR_FAILURE;
  1.4030 +  }
  1.4031 +
  1.4032 +  passed("Test transaction RedoTransaction() error");
  1.4033 +
  1.4034 +  /*******************************************************************
  1.4035 +   *
  1.4036 +   * Make sure that setting the transaction manager's max transaction
  1.4037 +   * count to zero, clears both the undo and redo stacks, and executes
  1.4038 +   * all new commands without pushing them on the undo stack!
  1.4039 +   *
  1.4040 +   *******************************************************************/
  1.4041 +
  1.4042 +  result = mgr->SetMaxTransactionCount(0);
  1.4043 +
  1.4044 +  if (NS_FAILED(result)) {
  1.4045 +    fail("SetMaxTransactionCount(0) failed. (%d)\n", result);
  1.4046 +    return result;
  1.4047 +  }
  1.4048 +
  1.4049 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.4050 +
  1.4051 +  if (NS_FAILED(result)) {
  1.4052 +    fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.4053 +         result);
  1.4054 +    return result;
  1.4055 +  }
  1.4056 +
  1.4057 +  if (numitems != 0) {
  1.4058 +    fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.4059 +         numitems, result);
  1.4060 +    return NS_ERROR_FAILURE;
  1.4061 +  }
  1.4062 +
  1.4063 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.4064 +
  1.4065 +  if (NS_FAILED(result)) {
  1.4066 +    fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.4067 +         result);
  1.4068 +    return result;
  1.4069 +  }
  1.4070 +
  1.4071 +  if (numitems != 0) {
  1.4072 +    fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.4073 +         numitems, result);
  1.4074 +    return NS_ERROR_FAILURE;
  1.4075 +  }
  1.4076 +
  1.4077 +  for (i = 1; i <= 20; i++) {
  1.4078 +    tximpl = factory->create(mgr, NONE_FLAG);
  1.4079 +
  1.4080 +    if (!tximpl) {
  1.4081 +      fail("Failed to allocate transaction %d.\n", i);
  1.4082 +      return NS_ERROR_OUT_OF_MEMORY;
  1.4083 +    }
  1.4084 +
  1.4085 +    tx = 0;
  1.4086 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.4087 +    if (NS_FAILED(result)) {
  1.4088 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.4089 +           i, result);
  1.4090 +      return result;
  1.4091 +    }
  1.4092 +
  1.4093 +    result = mgr->BeginBatch(nullptr);
  1.4094 +
  1.4095 +    if (NS_FAILED(result)) {
  1.4096 +      fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.4097 +      return result;
  1.4098 +    }
  1.4099 +
  1.4100 +    result = mgr->DoTransaction(tx);
  1.4101 +    if (NS_FAILED(result)) {
  1.4102 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.4103 +      return result;
  1.4104 +    }
  1.4105 +
  1.4106 +    tx->Release();
  1.4107 +
  1.4108 +    result = mgr->EndBatch(false);
  1.4109 +
  1.4110 +    if (NS_FAILED(result)) {
  1.4111 +      fail("EndBatch(false) failed. (%d)\n", result);
  1.4112 +      return result;
  1.4113 +    }
  1.4114 +
  1.4115 +    result = mgr->GetNumberOfUndoItems(&numitems);
  1.4116 +
  1.4117 +    if (NS_FAILED(result)) {
  1.4118 +      fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  1.4119 +           result);
  1.4120 +      return result;
  1.4121 +    }
  1.4122 +
  1.4123 +    if (numitems != 0) {
  1.4124 +      fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1.4125 +           numitems, result);
  1.4126 +      return NS_ERROR_FAILURE;
  1.4127 +    }
  1.4128 +
  1.4129 +    result = mgr->GetNumberOfRedoItems(&numitems);
  1.4130 +
  1.4131 +    if (NS_FAILED(result)) {
  1.4132 +      fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.4133 +           result);
  1.4134 +      return result;
  1.4135 +    }
  1.4136 +
  1.4137 +    if (numitems != 0) {
  1.4138 +      fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.4139 +           numitems, result);
  1.4140 +      return NS_ERROR_FAILURE;
  1.4141 +    }
  1.4142 +  }
  1.4143 +
  1.4144 +  passed("Test max transaction count of zero");
  1.4145 +
  1.4146 +  /*******************************************************************
  1.4147 +   *
  1.4148 +   * Release the transaction manager. Any transactions on the undo
  1.4149 +   * and redo stack should automatically be released:
  1.4150 +   *
  1.4151 +   *******************************************************************/
  1.4152 +
  1.4153 +  result = mgr->SetMaxTransactionCount(-1);
  1.4154 +
  1.4155 +  if (NS_FAILED(result)) {
  1.4156 +    fail("SetMaxTransactionCount(0) failed. (%d)\n", result);
  1.4157 +    return result;
  1.4158 +  }
  1.4159 +
  1.4160 +  // Push 20 transactions on the undo stack:
  1.4161 +
  1.4162 +  for (i = 1; i <= 20; i++) {
  1.4163 +    tximpl = factory->create(mgr, NONE_FLAG);
  1.4164 +
  1.4165 +    if (!tximpl) {
  1.4166 +      fail("Failed to allocate transaction %d.\n", i);
  1.4167 +      return NS_ERROR_OUT_OF_MEMORY;
  1.4168 +    }
  1.4169 +
  1.4170 +    tx = 0;
  1.4171 +    result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.4172 +    if (NS_FAILED(result)) {
  1.4173 +      fail("QueryInterface() failed for transaction %d. (%d)\n",
  1.4174 +           i, result);
  1.4175 +      return result;
  1.4176 +    }
  1.4177 +
  1.4178 +    result = mgr->BeginBatch(nullptr);
  1.4179 +
  1.4180 +    if (NS_FAILED(result)) {
  1.4181 +      fail("BeginBatch(nullptr) failed. (%d)\n", result);
  1.4182 +      return result;
  1.4183 +    }
  1.4184 +
  1.4185 +    result = mgr->DoTransaction(tx);
  1.4186 +    if (NS_FAILED(result)) {
  1.4187 +      fail("Failed to execute transaction %d. (%d)\n", i, result);
  1.4188 +      return result;
  1.4189 +    }
  1.4190 +
  1.4191 +    tx->Release();
  1.4192 +
  1.4193 +    result = mgr->EndBatch(false);
  1.4194 +
  1.4195 +    if (NS_FAILED(result)) {
  1.4196 +      fail("EndBatch(false) failed. (%d)\n", result);
  1.4197 +      return result;
  1.4198 +    }
  1.4199 +
  1.4200 +    result = mgr->GetNumberOfUndoItems(&numitems);
  1.4201 +
  1.4202 +    if (NS_FAILED(result)) {
  1.4203 +      fail("GetNumberOfUndoItems() on undo stack with %d items failed. (%d)\n",
  1.4204 +           i, result);
  1.4205 +      return result;
  1.4206 +    }
  1.4207 +
  1.4208 +    if (numitems != i) {
  1.4209 +      fail("GetNumberOfUndoItems() expected %d got %d. (%d)\n",
  1.4210 +           i, numitems, result);
  1.4211 +      return NS_ERROR_FAILURE;
  1.4212 +    }
  1.4213 +
  1.4214 +    result = mgr->GetNumberOfRedoItems(&numitems);
  1.4215 +
  1.4216 +    if (NS_FAILED(result)) {
  1.4217 +      fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1.4218 +           result);
  1.4219 +      return result;
  1.4220 +    }
  1.4221 +
  1.4222 +    if (numitems != 0) {
  1.4223 +      fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1.4224 +           numitems, result);
  1.4225 +      return NS_ERROR_FAILURE;
  1.4226 +    }
  1.4227 +  }
  1.4228 +
  1.4229 +  for (i = 1; i <= 10; i++) {
  1.4230 +
  1.4231 +    result = mgr->UndoTransaction();
  1.4232 +    if (NS_FAILED(result)) {
  1.4233 +      fail("Failed to undo transaction %d. (%d)\n", i, result);
  1.4234 +      return result;
  1.4235 +    }
  1.4236 +  }
  1.4237 +  result = mgr->GetNumberOfUndoItems(&numitems);
  1.4238 +
  1.4239 +  if (NS_FAILED(result)) {
  1.4240 +    fail("GetNumberOfUndoItems() on empty undo stack with 10 items failed. (%d)\n",
  1.4241 +         result);
  1.4242 +    return result;
  1.4243 +  }
  1.4244 +
  1.4245 +  if (numitems != 10) {
  1.4246 +    fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  1.4247 +         numitems, result);
  1.4248 +    return NS_ERROR_FAILURE;
  1.4249 +  }
  1.4250 +
  1.4251 +  result = mgr->GetNumberOfRedoItems(&numitems);
  1.4252 +
  1.4253 +  if (NS_FAILED(result)) {
  1.4254 +    fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
  1.4255 +         result);
  1.4256 +    return result;
  1.4257 +  }
  1.4258 +
  1.4259 +  if (numitems != 10) {
  1.4260 +    fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
  1.4261 +         numitems, result);
  1.4262 +    return NS_ERROR_FAILURE;
  1.4263 +  }
  1.4264 +
  1.4265 +  result = mgr->Clear();
  1.4266 +  if (NS_FAILED(result)) {
  1.4267 +    fail("Clear() failed. (%d)\n", result);
  1.4268 +    return result;
  1.4269 +  }
  1.4270 +
  1.4271 +  passed("Release the transaction manager");
  1.4272 +
  1.4273 +  /*******************************************************************
  1.4274 +   *
  1.4275 +   * Make sure number of transactions created matches number of
  1.4276 +   * transactions destroyed!
  1.4277 +   *
  1.4278 +   *******************************************************************/
  1.4279 +
  1.4280 +  /* Disabled because the current cycle collector doesn't delete
  1.4281 +     cycle collectable objects synchronously.
  1.4282 +  if (sConstructorCount != sDestructorCount) {
  1.4283 +    fail("Transaction constructor count (%d) != destructor count (%d).\n",
  1.4284 +         sConstructorCount, sDestructorCount);
  1.4285 +    return NS_ERROR_FAILURE;
  1.4286 +  }*/
  1.4287 +
  1.4288 +  passed("Number of transactions created and destroyed match");
  1.4289 +  passed("%d transactions processed during quick batch test",
  1.4290 +         sConstructorCount);
  1.4291 +
  1.4292 +  return NS_OK;
  1.4293 +}
  1.4294 +
  1.4295 +nsresult
  1.4296 +simple_batch_test()
  1.4297 +{
  1.4298 +  /*******************************************************************
  1.4299 +   *
  1.4300 +   * Initialize globals for test.
  1.4301 +   *
  1.4302 +   *******************************************************************/
  1.4303 +  reset_globals();
  1.4304 +  sDestructorOrderArr = sSimpleBatchTestDestructorOrderArr;
  1.4305 +  sDoOrderArr         = sSimpleBatchTestDoOrderArr;
  1.4306 +  sUndoOrderArr       = sSimpleBatchTestUndoOrderArr;
  1.4307 +  sRedoOrderArr       = sSimpleBatchTestRedoOrderArr;
  1.4308 +
  1.4309 +  /*******************************************************************
  1.4310 +   *
  1.4311 +   * Run the quick batch test.
  1.4312 +   *
  1.4313 +   *******************************************************************/
  1.4314 +
  1.4315 +  printf("\n-----------------------------------------------------\n");
  1.4316 +  printf("- Begin Batch Transaction Test:\n");
  1.4317 +  printf("-----------------------------------------------------\n");
  1.4318 +
  1.4319 +  SimpleTransactionFactory factory;
  1.4320 +
  1.4321 +  return quick_batch_test(&factory);
  1.4322 +}
  1.4323 +
  1.4324 +nsresult
  1.4325 +aggregation_batch_test()
  1.4326 +{
  1.4327 +  /*******************************************************************
  1.4328 +   *
  1.4329 +   * Initialize globals for test.
  1.4330 +   *
  1.4331 +   *******************************************************************/
  1.4332 +
  1.4333 +  reset_globals();
  1.4334 +  sDestructorOrderArr = sAggregateBatchTestDestructorOrderArr;
  1.4335 +  sDoOrderArr         = sAggregateBatchTestDoOrderArr;
  1.4336 +  sUndoOrderArr       = sAggregateBatchTestUndoOrderArr;
  1.4337 +  sRedoOrderArr       = sAggregateBatchTestRedoOrderArr;
  1.4338 +
  1.4339 +  /*******************************************************************
  1.4340 +   *
  1.4341 +   * Run the quick batch test.
  1.4342 +   *
  1.4343 +   *******************************************************************/
  1.4344 +
  1.4345 +  printf("\n-----------------------------------------------------\n");
  1.4346 +  printf("- Begin Batch Aggregate Transaction Test:\n");
  1.4347 +  printf("-----------------------------------------------------\n");
  1.4348 +
  1.4349 +  AggregateTransactionFactory factory(3, 2, BATCH_FLAG);
  1.4350 +
  1.4351 +  return quick_batch_test(&factory);
  1.4352 +}
  1.4353 +
  1.4354 +/**
  1.4355 + * Create 'iterations * (iterations + 1) / 2' transactions;
  1.4356 + * do/undo/redo/undo them.
  1.4357 + **/
  1.4358 +nsresult
  1.4359 +stress_test(TestTransactionFactory *factory, int32_t iterations)
  1.4360 +{
  1.4361 +  printf("Stress test of %i iterations (may take a while) ... ", iterations);
  1.4362 +  fflush(stdout);
  1.4363 +
  1.4364 +  nsresult result;
  1.4365 +
  1.4366 +  /*******************************************************************
  1.4367 +   *
  1.4368 +   * Create a transaction manager:
  1.4369 +   *
  1.4370 +   *******************************************************************/
  1.4371 +
  1.4372 +  nsCOMPtr<nsITransactionManager> mgr =
  1.4373 +    do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
  1.4374 +  if (NS_FAILED(result) || !mgr) {
  1.4375 +    fail("Failed to create Transaction Manager instance.\n");
  1.4376 +    return NS_ERROR_OUT_OF_MEMORY;
  1.4377 +  }
  1.4378 +
  1.4379 +  int32_t i, j;
  1.4380 +  nsITransaction *tx;
  1.4381 +
  1.4382 +  for (i = 1; i <= iterations; i++) {
  1.4383 +    /*******************************************************************
  1.4384 +     *
  1.4385 +     * Create and execute a bunch of transactions:
  1.4386 +     *
  1.4387 +     *******************************************************************/
  1.4388 +
  1.4389 +    for (j = 1; j <= i; j++) {
  1.4390 +      TestTransaction *tximpl = factory->create(mgr, NONE_FLAG);
  1.4391 +
  1.4392 +      if (!tximpl) {
  1.4393 +        fail("Failed to allocate transaction %d-%d.\n", i, j);
  1.4394 +        return NS_ERROR_OUT_OF_MEMORY;
  1.4395 +      }
  1.4396 +
  1.4397 +      tx = 0;
  1.4398 +      result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1.4399 +      if (NS_FAILED(result)) {
  1.4400 +        fail("QueryInterface() failed for transaction %d-%d. (%d)\n",
  1.4401 +             i, j, result);
  1.4402 +        return result;
  1.4403 +      }
  1.4404 +
  1.4405 +      result = mgr->DoTransaction(tx);
  1.4406 +      if (NS_FAILED(result)) {
  1.4407 +        fail("Failed to execute transaction %d-%d. (%d)\n",
  1.4408 +             i, j, result);
  1.4409 +        return result;
  1.4410 +      }
  1.4411 +
  1.4412 +      tx->Release();
  1.4413 +    }
  1.4414 +
  1.4415 +    /*******************************************************************
  1.4416 +     *
  1.4417 +     * Undo all the transactions:
  1.4418 +     *
  1.4419 +     *******************************************************************/
  1.4420 +
  1.4421 +    for (j = 1; j <= i; j++) {
  1.4422 +      result = mgr->UndoTransaction();
  1.4423 +      if (NS_FAILED(result)) {
  1.4424 +        fail("Failed to undo transaction %d-%d. (%d)\n", i, j, result);
  1.4425 +        return result;
  1.4426 +      }
  1.4427 +    }
  1.4428 +
  1.4429 +    /*******************************************************************
  1.4430 +     *
  1.4431 +     * Redo all the transactions:
  1.4432 +     *
  1.4433 +     *******************************************************************/
  1.4434 +
  1.4435 +    for (j = 1; j <= i; j++) {
  1.4436 +      result = mgr->RedoTransaction();
  1.4437 +      if (NS_FAILED(result)) {
  1.4438 +        fail("Failed to redo transaction %d-%d. (%d)\n", i, j, result);
  1.4439 +        return result;
  1.4440 +      }
  1.4441 +    }
  1.4442 +
  1.4443 +    /*******************************************************************
  1.4444 +     *
  1.4445 +     * Undo all the transactions again so that they all end up on
  1.4446 +     * the redo stack for pruning the next time we execute a new
  1.4447 +     * transaction
  1.4448 +     *
  1.4449 +     *******************************************************************/
  1.4450 +
  1.4451 +    for (j = 1; j <= i; j++) {
  1.4452 +      result = mgr->UndoTransaction();
  1.4453 +      if (NS_FAILED(result)) {
  1.4454 +        fail("Failed to undo transaction %d-%d. (%d)\n", i, j, result);
  1.4455 +        return result;
  1.4456 +      }
  1.4457 +    }
  1.4458 +
  1.4459 +    // Trivial feedback not to let the user think the test is stuck.
  1.4460 +    if (MOZ_UNLIKELY(j % 100 == 0))
  1.4461 +      printf("%i ", j);
  1.4462 +  } // for, iterations.
  1.4463 +
  1.4464 +  printf("passed\n");
  1.4465 +
  1.4466 +  result = mgr->Clear();
  1.4467 +  if (NS_FAILED(result)) {
  1.4468 +    fail("Clear() failed. (%d)\n", result);
  1.4469 +    return result;
  1.4470 +  }
  1.4471 +
  1.4472 +  /* Disabled because the current cycle collector doesn't delete
  1.4473 +     cycle collectable objects synchronously.
  1.4474 +  if (sConstructorCount != sDestructorCount) {
  1.4475 +    fail("Transaction constructor count (%d) != destructor count (%d).\n",
  1.4476 +         sConstructorCount, sDestructorCount);
  1.4477 +    return NS_ERROR_FAILURE;
  1.4478 +  }*/
  1.4479 +
  1.4480 +  passed("%d transactions processed during stress test", sConstructorCount);
  1.4481 +
  1.4482 +  return NS_OK;
  1.4483 +}
  1.4484 +
  1.4485 +nsresult
  1.4486 +simple_stress_test()
  1.4487 +{
  1.4488 +  /*******************************************************************
  1.4489 +   *
  1.4490 +   * Initialize globals for test.
  1.4491 +   *
  1.4492 +   *******************************************************************/
  1.4493 +
  1.4494 +  reset_globals();
  1.4495 +
  1.4496 +  /*******************************************************************
  1.4497 +   *
  1.4498 +   * Do the stress test:
  1.4499 +   *
  1.4500 +   *******************************************************************/
  1.4501 +
  1.4502 +  printf("\n-----------------------------------------------------\n");
  1.4503 +  printf("- Simple Transaction Stress Test:\n");
  1.4504 +  printf("-----------------------------------------------------\n");
  1.4505 +
  1.4506 +  SimpleTransactionFactory factory;
  1.4507 +
  1.4508 +  int32_t iterations =
  1.4509 +#ifdef DEBUG
  1.4510 +  10
  1.4511 +#else
  1.4512 +  //
  1.4513 +  // 1500 iterations sends 1,125,750 transactions through the system!!
  1.4514 +  //
  1.4515 +  1500
  1.4516 +#endif
  1.4517 +  ;
  1.4518 +  return stress_test(&factory, iterations);
  1.4519 +}
  1.4520 +
  1.4521 +nsresult
  1.4522 +aggregation_stress_test()
  1.4523 +{
  1.4524 +  /*******************************************************************
  1.4525 +   *
  1.4526 +   * Initialize globals for test.
  1.4527 +   *
  1.4528 +   *******************************************************************/
  1.4529 +
  1.4530 +  reset_globals();
  1.4531 +
  1.4532 +  /*******************************************************************
  1.4533 +   *
  1.4534 +   * Do the stress test:
  1.4535 +   *
  1.4536 +   *******************************************************************/
  1.4537 +
  1.4538 +  printf("\n-----------------------------------------------------\n");
  1.4539 +  printf("- Aggregate Transaction Stress Test:\n");
  1.4540 +  printf("-----------------------------------------------------\n");
  1.4541 +
  1.4542 +  AggregateTransactionFactory factory(3, 4);
  1.4543 +
  1.4544 +  int32_t iterations =
  1.4545 +#ifdef DEBUG
  1.4546 +  10
  1.4547 +#else
  1.4548 +  //
  1.4549 +  // 500 iterations sends 2,630,250 transactions through the system!!
  1.4550 +  //
  1.4551 +  500
  1.4552 +#endif
  1.4553 +  ;
  1.4554 +  return stress_test(&factory, iterations);
  1.4555 +}
  1.4556 +
  1.4557 +nsresult
  1.4558 +aggregation_batch_stress_test()
  1.4559 +{
  1.4560 +  /*******************************************************************
  1.4561 +   *
  1.4562 +   * Initialize globals for test.
  1.4563 +   *
  1.4564 +   *******************************************************************/
  1.4565 +
  1.4566 +  reset_globals();
  1.4567 +
  1.4568 +  /*******************************************************************
  1.4569 +   *
  1.4570 +   * Do the stress test:
  1.4571 +   *
  1.4572 +   *******************************************************************/
  1.4573 +
  1.4574 +  printf("\n-----------------------------------------------------\n");
  1.4575 +  printf("- Aggregate Batch Transaction Stress Test:\n");
  1.4576 +  printf("-----------------------------------------------------\n");
  1.4577 +
  1.4578 +  AggregateTransactionFactory factory(3, 4, BATCH_FLAG);
  1.4579 +
  1.4580 +  int32_t iterations =
  1.4581 +#ifdef DEBUG
  1.4582 +  10
  1.4583 +#else
  1.4584 +#if defined(MOZ_ASAN) || defined(MOZ_WIDGET_ANDROID)
  1.4585 +  // See Bug 929985: 500 is too many for ASAN and Android, 100 is safe.
  1.4586 +  100
  1.4587 +#else
  1.4588 +  //
  1.4589 +  // 500 iterations sends 2,630,250 transactions through the system!!
  1.4590 +  //
  1.4591 +  500
  1.4592 +#endif
  1.4593 +#endif
  1.4594 +  ;
  1.4595 +  return stress_test(&factory, iterations);
  1.4596 +}
  1.4597 +
  1.4598 +int
  1.4599 +main (int argc, char *argv[])
  1.4600 +{
  1.4601 +  ScopedXPCOM xpcom("nsITransactionManager");
  1.4602 +  if (xpcom.failed())
  1.4603 +    return 1;
  1.4604 +
  1.4605 +  nsresult result;
  1.4606 +
  1.4607 +  //
  1.4608 +  // quick_test() part:
  1.4609 +  //
  1.4610 +
  1.4611 +  result = simple_test();
  1.4612 +  NS_ENSURE_SUCCESS(result, 1);
  1.4613 +
  1.4614 +  result = aggregation_test();
  1.4615 +  NS_ENSURE_SUCCESS(result, 1);
  1.4616 +
  1.4617 +  //
  1.4618 +  // quick_batch_test() part:
  1.4619 +  //
  1.4620 +
  1.4621 +  result = simple_batch_test();
  1.4622 +  NS_ENSURE_SUCCESS(result, 1);
  1.4623 +
  1.4624 +  result = aggregation_batch_test();
  1.4625 +  NS_ENSURE_SUCCESS(result, 1);
  1.4626 +
  1.4627 +  //
  1.4628 +  // stress_test() part:
  1.4629 +  //
  1.4630 +
  1.4631 +  result = simple_stress_test();
  1.4632 +  NS_ENSURE_SUCCESS(result, 1);
  1.4633 +
  1.4634 +  result = aggregation_stress_test();
  1.4635 +  NS_ENSURE_SUCCESS(result, 1);
  1.4636 +
  1.4637 +  result = aggregation_batch_stress_test();
  1.4638 +  NS_ENSURE_SUCCESS(result, 1);
  1.4639 +
  1.4640 +  return 0;
  1.4641 +}

mercurial