editor/txmgr/tests/TestTXMgr.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "TestHarness.h"
     8 #include "nsITransactionManager.h"
     9 #include "nsComponentManagerUtils.h"
    10 #include "mozilla/Likely.h"
    12 static int32_t sConstructorCount     = 0;
    13 static int32_t sDestructorCount      = 0;
    14 static int32_t *sDestructorOrderArr  = 0;
    15 static int32_t sDoCount              = 0;
    16 static int32_t *sDoOrderArr          = 0;
    17 static int32_t sUndoCount            = 0;
    18 static int32_t *sUndoOrderArr        = 0;
    19 static int32_t sRedoCount            = 0;
    20 static int32_t *sRedoOrderArr        = 0;
    22 // #define ENABLE_DEBUG_PRINTFS 1
    24 int32_t sSimpleTestDestructorOrderArr[] = {
    25           2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,
    26          16,  17,  18,  19,  20,  21,   1,  22,  23,  24,  25,  26,  27,  28,
    27          29,  30,  31,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,
    28          53,  54,  55,  56,  57,  58,  59,  60,  61,  41,  40,  62,  39,  38,
    29          37,  36,  35,  34,  33,  32,  68,  63,  64,  65,  66,  67,  69,  71,
    30          70,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
    31          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
    32          99, 100, 101, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 131,
    33         130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117,
    34         116, 115, 114, 113, 112 };
    36 int32_t sSimpleTestDoOrderArr[] = {
    37           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
    38          15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
    39          29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
    40          43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
    41          57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
    42          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
    43          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
    44          99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
    45         113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
    46         127, 128, 129, 130, 131 };
    48 int32_t sSimpleTestUndoOrderArr[] = {
    49          41,  40,  39,  38,  62,  39,  38,  37,  69,  71,  70, 111, 110, 109,
    50         108, 107, 106, 105, 104, 103, 102, 131, 130, 129, 128, 127, 126, 125,
    51         124, 123, 122 };
    53 static int32_t sSimpleTestRedoOrderArr[] = {
    54          38,  39,  70 };
    56 int32_t sAggregateTestDestructorOrderArr[] = {
    57          14,  13,  12,  11,  10,   9,   8,  21,  20,  19,  18,  17,  16,  15,
    58          28,  27,  26,  25,  24,  23,  22,  35,  34,  33,  32,  31,  30,  29,
    59          42,  41,  40,  39,  38,  37,  36,  49,  48,  47,  46,  45,  44,  43,
    60          56,  55,  54,  53,  52,  51,  50,  63,  62,  61,  60,  59,  58,  57,
    61          70,  69,  68,  67,  66,  65,  64,  77,  76,  75,  74,  73,  72,  71,
    62          84,  83,  82,  81,  80,  79,  78,  91,  90,  89,  88,  87,  86,  85,
    63          98,  97,  96,  95,  94,  93,  92, 105, 104, 103, 102, 101, 100,  99,
    64         112, 111, 110, 109, 108, 107, 106, 119, 118, 117, 116, 115, 114, 113,
    65         126, 125, 124, 123, 122, 121, 120, 133, 132, 131, 130, 129, 128, 127,
    66         140, 139, 138, 137, 136, 135, 134, 147, 146, 145, 144, 143, 142, 141,
    67           7,   6,   5,   4,   3,   2,   1, 154, 153, 152, 151, 150, 149, 148,
    68         161, 160, 159, 158, 157, 156, 155, 168, 167, 166, 165, 164, 163, 162,
    69         175, 174, 173, 172, 171, 170, 169, 182, 181, 180, 179, 178, 177, 176,
    70         189, 188, 187, 186, 185, 184, 183, 196, 195, 194, 193, 192, 191, 190,
    71         203, 202, 201, 200, 199, 198, 197, 210, 209, 208, 207, 206, 205, 204,
    72         217, 216, 215, 214, 213, 212, 211, 294, 293, 292, 291, 290, 289, 288,
    73         301, 300, 299, 298, 297, 296, 295, 308, 307, 306, 305, 304, 303, 302,
    74         315, 314, 313, 312, 311, 310, 309, 322, 321, 320, 319, 318, 317, 316,
    75         329, 328, 327, 326, 325, 324, 323, 336, 335, 334, 333, 332, 331, 330,
    76         343, 342, 341, 340, 339, 338, 337, 350, 349, 348, 347, 346, 345, 344,
    77         357, 356, 355, 354, 353, 352, 351, 364, 363, 362, 361, 360, 359, 358,
    78         371, 370, 369, 368, 367, 366, 365, 378, 377, 376, 375, 374, 373, 372,
    79         385, 384, 383, 382, 381, 380, 379, 392, 391, 390, 389, 388, 387, 386,
    80         399, 398, 397, 396, 395, 394, 393, 406, 405, 404, 403, 402, 401, 400,
    81         413, 412, 411, 410, 409, 408, 407, 420, 419, 418, 417, 416, 415, 414,
    82         427, 426, 425, 424, 423, 422, 421, 287, 286, 285, 284, 283, 282, 281,
    83         280, 279, 278, 277, 276, 275, 274, 434, 433, 432, 431, 430, 429, 428,
    84         273, 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260,
    85         259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246,
    86         245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232,
    87         231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218,
    88         472, 471, 470, 441, 440, 439, 438, 437, 436, 435, 448, 447, 446, 445,
    89         444, 443, 442, 455, 454, 453, 452, 451, 450, 449, 462, 461, 460, 459,
    90         458, 457, 456, 469, 468, 467, 466, 465, 464, 463, 479, 478, 477, 476,
    91         475, 474, 473, 493, 492, 491, 490, 489, 488, 487, 486, 485, 484, 483,
    92         482, 481, 480, 496, 497, 495, 499, 500, 498, 494, 503, 504, 502, 506,
    93         507, 505, 501, 510, 511, 509, 513, 514, 512, 508, 517, 518, 516, 520,
    94         521, 519, 515, 524, 525, 523, 527, 528, 526, 522, 531, 532, 530, 534,
    95         535, 533, 529, 538, 539, 537, 541, 542, 540, 536, 545, 546, 544, 548,
    96         549, 547, 543, 552, 553, 551, 555, 556, 554, 550, 559, 560, 558, 562,
    97         563, 561, 557, 566, 567, 565, 569, 570, 568, 564, 573, 574, 572, 576,
    98         577, 575, 571, 580, 581, 579, 583, 584, 582, 578, 587, 588, 586, 590,
    99         591, 589, 585, 594, 595, 593, 597, 598, 596, 592, 601, 602, 600, 604,
   100         605, 603, 599, 608, 609, 607, 611, 612, 610, 606, 615, 616, 614, 618,
   101         619, 617, 613, 622, 623, 621, 625, 626, 624, 620, 629, 630, 628, 632,
   102         633, 631, 627, 640, 639, 638, 637, 636, 635, 634, 647, 646, 645, 644,
   103         643, 642, 641, 654, 653, 652, 651, 650, 649, 648, 661, 660, 659, 658,
   104         657, 656, 655, 668, 667, 666, 665, 664, 663, 662, 675, 674, 673, 672,
   105         671, 670, 669, 682, 681, 680, 679, 678, 677, 676, 689, 688, 687, 686,
   106         685, 684, 683, 696, 695, 694, 693, 692, 691, 690, 703, 702, 701, 700,
   107         699, 698, 697, 773, 772, 771, 770, 769, 768, 767, 766, 765, 764, 763,
   108         762, 761, 760, 759, 758, 757, 756, 755, 754, 753, 752, 751, 750, 749,
   109         748, 747, 746, 745, 744, 743, 742, 741, 740, 739, 738, 737, 736, 735,
   110         734, 733, 732, 731, 730, 729, 728, 727, 726, 725, 724, 723, 722, 721,
   111         720, 719, 718, 717, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707,
   112         706, 705, 704, 913, 912, 911, 910, 909, 908, 907, 906, 905, 904, 903,
   113         902, 901, 900, 899, 898, 897, 896, 895, 894, 893, 892, 891, 890, 889,
   114         888, 887, 886, 885, 884, 883, 882, 881, 880, 879, 878, 877, 876, 875,
   115         874, 873, 872, 871, 870, 869, 868, 867, 866, 865, 864, 863, 862, 861,
   116         860, 859, 858, 857, 856, 855, 854, 853, 852, 851, 850, 849, 848, 847,
   117         846, 845, 844, 843, 842, 841, 840, 839, 838, 837, 836, 835, 834, 833,
   118         832, 831, 830, 829, 828, 827, 826, 825, 824, 823, 822, 821, 820, 819,
   119         818, 817, 816, 815, 814, 813, 812, 811, 810, 809, 808, 807, 806, 805,
   120         804, 803, 802, 801, 800, 799, 798, 797, 796, 795, 794, 793, 792, 791,
   121         790, 789, 788, 787, 786, 785, 784, 783, 782, 781, 780, 779, 778, 777,
   122         776, 775, 774 };
   124 int32_t sAggregateTestDoOrderArr[] = {
   125           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
   126          15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
   127          29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
   128          43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
   129          57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
   130          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
   131          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
   132          99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
   133         113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
   134         127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
   135         141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
   136         155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
   137         169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
   138         183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
   139         197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
   140         211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
   141         225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
   142         239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
   143         253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
   144         267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
   145         281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
   146         295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
   147         309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
   148         323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
   149         337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
   150         351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
   151         365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
   152         379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392,
   153         393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406,
   154         407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
   155         421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
   156         435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
   157         449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
   158         463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476,
   159         477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
   160         491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504,
   161         505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518,
   162         519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532,
   163         533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546,
   164         547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
   165         561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
   166         575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588,
   167         589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602,
   168         603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616,
   169         617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630,
   170         631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644,
   171         645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658,
   172         659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
   173         673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686,
   174         687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700,
   175         701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714,
   176         715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728,
   177         729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742,
   178         743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756,
   179         757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770,
   180         771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784,
   181         785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798,
   182         799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812,
   183         813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826,
   184         827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840,
   185         841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854,
   186         855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868,
   187         869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882,
   188         883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896,
   189         897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910,
   190         911, 912, 913 };
   192 int32_t sAggregateTestUndoOrderArr[] = {
   193         287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274,
   194         273, 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260,
   195         434, 433, 432, 431, 430, 429, 428, 273, 272, 271, 270, 269, 268, 267,
   196         266, 265, 264, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253,
   197         479, 478, 477, 476, 475, 493, 492, 491, 490, 489, 488, 487, 486, 485,
   198         484, 483, 482, 481, 480, 485, 484, 483, 482, 481, 480, 773, 772, 771,
   199         770, 769, 768, 767, 766, 765, 764, 763, 762, 761, 760, 759, 758, 757,
   200         756, 755, 754, 753, 752, 751, 750, 749, 748, 747, 746, 745, 744, 743,
   201         742, 741, 740, 739, 738, 737, 736, 735, 734, 733, 732, 731, 730, 729,
   202         728, 727, 726, 725, 724, 723, 722, 721, 720, 719, 718, 717, 716, 715,
   203         714, 713, 712, 711, 710, 709, 708, 707, 706, 705, 704, 913, 912, 911,
   204         910, 909, 908, 907, 906, 905, 904, 903, 902, 901, 900, 899, 898, 897,
   205         896, 895, 894, 893, 892, 891, 890, 889, 888, 887, 886, 885, 884, 883,
   206         882, 881, 880, 879, 878, 877, 876, 875, 874, 873, 872, 871, 870, 869,
   207         868, 867, 866, 865, 864, 863, 862, 861, 860, 859, 858, 857, 856, 855,
   208         854, 853, 852, 851, 850, 849, 848, 847, 846, 845, 844 };
   210 int32_t sAggregateTestRedoOrderArr[] = {
   211         260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
   212         476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486 };
   214 int32_t sSimpleBatchTestDestructorOrderArr[] = {
   215          21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,
   216          35,  36,  37,  38,  39,  40,  43,  42,  41,  64,  63,  62,  61,  60,
   217          59,  58,  57,  56,  55,  54,  53,  52,  51,  50,  49,  48,  47,  46,
   218          45,  44,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,  10,   9,
   219           8,   7,   6,   5,   4,   3,   2,   1,  65,  67,  66,  68,  69,  70,
   220          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
   221          85,  86,  87, 107, 106, 105, 104, 103, 102, 101, 100,  99,  98,  97,
   222          96,  95,  94,  93,  92,  91,  90,  89,  88 };
   224 int32_t sSimpleBatchTestDoOrderArr[] = {
   225           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
   226          15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
   227          29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
   228          43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
   229          57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
   230          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
   231          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
   232          99, 100, 101, 102, 103, 104, 105, 106, 107 };
   234 int32_t sSimpleBatchTestUndoOrderArr[] = {
   235          43,  42,  41,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,  10,
   236           9,   8,   7,   6,   5,   4,   3,   2,   1,  43,  42,  41,  63,  62,
   237          61,  60,  59,  58,  57,  56,  55,  54,  53,  52,  51,  50,  49,  48,
   238          47,  46,  45,  44,  65,  67,  66, 107, 106, 105, 104, 103, 102, 101,
   239         100,  99,  98 };
   241 int32_t sSimpleBatchTestRedoOrderArr[] = {
   242           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
   243          15,  16,  17,  18,  19,  20,  41,  42,  43,  66 };
   245 int32_t sAggregateBatchTestDestructorOrderArr[] = {
   246         147, 146, 145, 144, 143, 142, 141, 154, 153, 152, 151, 150, 149, 148,
   247         161, 160, 159, 158, 157, 156, 155, 168, 167, 166, 165, 164, 163, 162,
   248         175, 174, 173, 172, 171, 170, 169, 182, 181, 180, 179, 178, 177, 176,
   249         189, 188, 187, 186, 185, 184, 183, 196, 195, 194, 193, 192, 191, 190,
   250         203, 202, 201, 200, 199, 198, 197, 210, 209, 208, 207, 206, 205, 204,
   251         217, 216, 215, 214, 213, 212, 211, 224, 223, 222, 221, 220, 219, 218,
   252         231, 230, 229, 228, 227, 226, 225, 238, 237, 236, 235, 234, 233, 232,
   253         245, 244, 243, 242, 241, 240, 239, 252, 251, 250, 249, 248, 247, 246,
   254         259, 258, 257, 256, 255, 254, 253, 266, 265, 264, 263, 262, 261, 260,
   255         273, 272, 271, 270, 269, 268, 267, 280, 279, 278, 277, 276, 275, 274,
   256         301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288,
   257         287, 286, 285, 284, 283, 282, 281, 444, 443, 442, 441, 440, 439, 438,
   258         437, 436, 435, 434, 433, 432, 431, 430, 429, 428, 427, 426, 425, 424,
   259         423, 422, 421, 420, 419, 418, 417, 416, 415, 414, 413, 412, 411, 410,
   260         409, 408, 407, 406, 405, 404, 403, 402, 401, 400, 399, 398, 397, 396,
   261         395, 394, 393, 392, 391, 390, 389, 388, 387, 386, 385, 384, 383, 382,
   262         381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 370, 369, 368,
   263         367, 366, 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, 354,
   264         353, 352, 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340,
   265         339, 338, 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326,
   266         325, 324, 323, 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, 312,
   267         311, 310, 309, 308, 307, 306, 305, 304, 303, 302, 140, 139, 138, 137,
   268         136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123,
   269         122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109,
   270         108, 107, 106, 105, 104, 103, 102, 101, 100,  99,  98,  97,  96,  95,
   271          94,  93,  92,  91,  90,  89,  88,  87,  86,  85,  84,  83,  82,  81,
   272          80,  79,  78,  77,  76,  75,  74,  73,  72,  71,  70,  69,  68,  67,
   273          66,  65,  64,  63,  62,  61,  60,  59,  58,  57,  56,  55,  54,  53,
   274          52,  51,  50,  49,  48,  47,  46,  45,  44,  43,  42,  41,  40,  39,
   275          38,  37,  36,  35,  34,  33,  32,  31,  30,  29,  28,  27,  26,  25,
   276          24,  23,  22,  21,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,
   277          10,   9,   8,   7,   6,   5,   4,   3,   2,   1, 451, 450, 449, 448,
   278         447, 446, 445, 465, 464, 463, 462, 461, 460, 459, 458, 457, 456, 455,
   279         454, 453, 452, 468, 469, 467, 471, 472, 470, 466, 475, 476, 474, 478,
   280         479, 477, 473, 482, 483, 481, 485, 486, 484, 480, 489, 490, 488, 492,
   281         493, 491, 487, 496, 497, 495, 499, 500, 498, 494, 503, 504, 502, 506,
   282         507, 505, 501, 510, 511, 509, 513, 514, 512, 508, 517, 518, 516, 520,
   283         521, 519, 515, 524, 525, 523, 527, 528, 526, 522, 531, 532, 530, 534,
   284         535, 533, 529, 538, 539, 537, 541, 542, 540, 536, 545, 546, 544, 548,
   285         549, 547, 543, 552, 553, 551, 555, 556, 554, 550, 559, 560, 558, 562,
   286         563, 561, 557, 566, 567, 565, 569, 570, 568, 564, 573, 574, 572, 576,
   287         577, 575, 571, 580, 581, 579, 583, 584, 582, 578, 587, 588, 586, 590,
   288         591, 589, 585, 594, 595, 593, 597, 598, 596, 592, 601, 602, 600, 604,
   289         605, 603, 599, 745, 744, 743, 742, 741, 740, 739, 738, 737, 736, 735,
   290         734, 733, 732, 731, 730, 729, 728, 727, 726, 725, 724, 723, 722, 721,
   291         720, 719, 718, 717, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707,
   292         706, 705, 704, 703, 702, 701, 700, 699, 698, 697, 696, 695, 694, 693,
   293         692, 691, 690, 689, 688, 687, 686, 685, 684, 683, 682, 681, 680, 679,
   294         678, 677, 676, 675, 674, 673, 672, 671, 670, 669, 668, 667, 666, 665,
   295         664, 663, 662, 661, 660, 659, 658, 657, 656, 655, 654, 653, 652, 651,
   296         650, 649, 648, 647, 646, 645, 644, 643, 642, 641, 640, 639, 638, 637,
   297         636, 635, 634, 633, 632, 631, 630, 629, 628, 627, 626, 625, 624, 623,
   298         622, 621, 620, 619, 618, 617, 616, 615, 614, 613, 612, 611, 610, 609,
   299         608, 607, 606 };
   301 int32_t sAggregateBatchTestDoOrderArr[] = {
   302           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
   303          15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
   304          29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
   305          43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
   306          57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
   307          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
   308          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
   309          99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
   310         113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
   311         127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
   312         141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
   313         155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
   314         169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
   315         183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
   316         197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
   317         211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
   318         225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
   319         239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
   320         253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
   321         267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
   322         281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
   323         295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
   324         309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
   325         323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
   326         337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
   327         351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
   328         365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
   329         379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392,
   330         393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406,
   331         407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
   332         421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
   333         435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
   334         449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
   335         463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476,
   336         477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
   337         491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504,
   338         505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518,
   339         519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532,
   340         533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546,
   341         547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
   342         561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
   343         575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588,
   344         589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602,
   345         603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616,
   346         617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630,
   347         631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644,
   348         645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658,
   349         659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
   350         673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686,
   351         687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700,
   352         701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714,
   353         715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728,
   354         729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742,
   355         743, 744, 745 };
   357 int32_t sAggregateBatchTestUndoOrderArr[] = {
   358         301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288,
   359         287, 286, 285, 284, 283, 282, 281, 140, 139, 138, 137, 136, 135, 134,
   360         133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120,
   361         119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106,
   362         105, 104, 103, 102, 101, 100,  99,  98,  97,  96,  95,  94,  93,  92,
   363          91,  90,  89,  88,  87,  86,  85,  84,  83,  82,  81,  80,  79,  78,
   364          77,  76,  75,  74,  73,  72,  71,  70,  69,  68,  67,  66,  65,  64,
   365          63,  62,  61,  60,  59,  58,  57,  56,  55,  54,  53,  52,  51,  50,
   366          49,  48,  47,  46,  45,  44,  43,  42,  41,  40,  39,  38,  37,  36,
   367          35,  34,  33,  32,  31,  30,  29,  28,  27,  26,  25,  24,  23,  22,
   368          21,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,  10,   9,   8,
   369           7,   6,   5,   4,   3,   2,   1, 301, 300, 299, 298, 297, 296, 295,
   370         294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281,
   371         441, 440, 439, 438, 437, 436, 435, 434, 433, 432, 431, 430, 429, 428,
   372         427, 426, 425, 424, 423, 422, 421, 420, 419, 418, 417, 416, 415, 414,
   373         413, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, 400,
   374         399, 398, 397, 396, 395, 394, 393, 392, 391, 390, 389, 388, 387, 386,
   375         385, 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372,
   376         371, 370, 369, 368, 367, 366, 365, 364, 363, 362, 361, 360, 359, 358,
   377         357, 356, 355, 354, 353, 352, 351, 350, 349, 348, 347, 346, 345, 344,
   378         343, 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, 331, 330,
   379         329, 328, 327, 326, 325, 324, 323, 322, 321, 320, 319, 318, 317, 316,
   380         315, 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, 304, 303, 302,
   381         451, 450, 449, 448, 447, 465, 464, 463, 462, 461, 460, 459, 458, 457,
   382         456, 455, 454, 453, 452, 457, 456, 455, 454, 453, 452, 745, 744, 743,
   383         742, 741, 740, 739, 738, 737, 736, 735, 734, 733, 732, 731, 730, 729,
   384         728, 727, 726, 725, 724, 723, 722, 721, 720, 719, 718, 717, 716, 715,
   385         714, 713, 712, 711, 710, 709, 708, 707, 706, 705, 704, 703, 702, 701,
   386         700, 699, 698, 697, 696, 695, 694, 693, 692, 691, 690, 689, 688, 687,
   387         686, 685, 684, 683, 682, 681, 680, 679, 678, 677, 676 };
   389 int32_t sAggregateBatchTestRedoOrderArr[] = {
   390           1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
   391          15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
   392          29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
   393          43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
   394          57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
   395          71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
   396          85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
   397          99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
   398         113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
   399         127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
   400         281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
   401         295, 296, 297, 298, 299, 300, 301, 448, 449, 450, 451, 452, 453, 454,
   402         455, 456, 457, 458 };
   404 #define TEST_TXMGR_IF_RELEASE(tx) if (tx) tx->Release(); // Release but don't clear pointer!
   406 class TestTransaction : public nsITransaction
   407 {
   408 public:
   410   TestTransaction() {}
   411   virtual ~TestTransaction() {}
   413   NS_DECL_ISUPPORTS
   414 };
   416 NS_IMPL_ISUPPORTS(TestTransaction, nsITransaction)
   418 class SimpleTransaction : public TestTransaction
   419 {
   420 protected:
   422 #define NONE_FLAG               0
   423 #define THROWS_DO_ERROR_FLAG    1
   424 #define THROWS_UNDO_ERROR_FLAG  2
   425 #define THROWS_REDO_ERROR_FLAG  4
   426 #define MERGE_FLAG              8
   427 #define TRANSIENT_FLAG         16
   428 #define BATCH_FLAG             32
   429 #define ALL_ERROR_FLAGS        (THROWS_DO_ERROR_FLAG|THROWS_UNDO_ERROR_FLAG|THROWS_REDO_ERROR_FLAG)
   431   int32_t mVal;
   432   int32_t mFlags;
   434 public:
   436   SimpleTransaction(int32_t aFlags=NONE_FLAG)
   437                     : mVal(++sConstructorCount), mFlags(aFlags)
   438   {}
   440   virtual ~SimpleTransaction()
   441   {
   442     //
   443     // Make sure transactions are being destroyed in the order we expect!
   444     // Notice that we don't check to see if we go past the end of the array.
   445     // This is done on purpose since we want to crash if the order array is out
   446     // of date.
   447     //
   448     /* Disabled because the current cycle collector doesn't delete
   449        cycle collectable objects synchronously, nor doesn't guarantee any order.
   450     if (sDestructorOrderArr && mVal != sDestructorOrderArr[sDestructorCount]) {
   451       fail("~SimpleTransaction expected %d got %d.\n",
   452            mVal, sDestructorOrderArr[sDestructorCount]);
   453       exit(-1);
   454     }
   455     */
   457     ++sDestructorCount;
   459 #ifdef ENABLE_DEBUG_PRINTFS
   460     printf("\n~SimpleTransaction: %d - 0x%.8x\n", mVal, (int32_t)this);
   461 #endif // ENABLE_DEBUG_PRINTFS
   463     mVal = -1;
   464   }
   466   NS_IMETHOD DoTransaction()
   467   {
   468     //
   469     // Make sure DoTransaction() is called in the order we expect!
   470     // Notice that we don't check to see if we go past the end of the array.
   471     // This is done on purpose since we want to crash if the order array is out
   472     // of date.
   473     //
   474     if (sDoOrderArr && mVal != sDoOrderArr[sDoCount]) {
   475       fail("DoTransaction expected %d got %d.\n",
   476            mVal, sDoOrderArr[sDoCount]);
   477       exit(-1);
   478     }
   480     ++sDoCount;
   482 #ifdef ENABLE_DEBUG_PRINTFS
   483     printf("\nSimpleTransaction.DoTransaction: %d - 0x%.8x\n", mVal, (int32_t)this);
   484 #endif // ENABLE_DEBUG_PRINTFS
   486     return (mFlags & THROWS_DO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
   487   }
   489   NS_IMETHOD UndoTransaction()
   490   {
   491     //
   492     // Make sure UndoTransaction() is called in the order we expect!
   493     // Notice that we don't check to see if we go past the end of the array.
   494     // This is done on purpose since we want to crash if the order array is out
   495     // of date.
   496     //
   497     if (sUndoOrderArr && mVal != sUndoOrderArr[sUndoCount]) {
   498       fail("UndoTransaction expected %d got %d.\n",
   499            mVal, sUndoOrderArr[sUndoCount]);
   500       exit(-1);
   501     }
   503     ++sUndoCount;
   505 #ifdef ENABLE_DEBUG_PRINTFS
   506     printf("\nSimpleTransaction.Undo: %d - 0x%.8x\n", mVal, (int32_t)this);
   507 #endif // ENABLE_DEBUG_PRINTFS
   509     return (mFlags & THROWS_UNDO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
   510   }
   512   NS_IMETHOD RedoTransaction()
   513   {
   514     //
   515     // Make sure RedoTransaction() is called in the order we expect!
   516     // Notice that we don't check to see if we go past the end of the array.
   517     // This is done on purpose since we want to crash if the order array is out
   518     // of date.
   519     //
   520     if (sRedoOrderArr && mVal != sRedoOrderArr[sRedoCount]) {
   521       fail("RedoTransaction expected %d got %d.\n",
   522            mVal, sRedoOrderArr[sRedoCount]);
   523       exit(-1);
   524     }
   526     ++sRedoCount;
   528 #ifdef ENABLE_DEBUG_PRINTFS
   529     printf("\nSimpleTransaction.Redo: %d - 0x%.8x\n", mVal, (int32_t)this);
   530 #endif // ENABLE_DEBUG_PRINTFS
   532     return (mFlags & THROWS_REDO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
   533   }
   535   NS_IMETHOD GetIsTransient(bool *aIsTransient)
   536   {
   537     if (aIsTransient)
   538       *aIsTransient = (mFlags & TRANSIENT_FLAG) ? true : false;
   540     return NS_OK;
   541   }
   543   NS_IMETHOD Merge(nsITransaction *aTransaction, bool *aDidMerge)
   544   {
   545     if (aDidMerge)
   546       *aDidMerge = (mFlags & MERGE_FLAG) ? true : false;
   548     return NS_OK;
   549   }
   550 };
   552 class AggregateTransaction : public SimpleTransaction
   553 {
   554 private:
   556   AggregateTransaction(nsITransactionManager *aTXMgr, int32_t aLevel,
   557                        int32_t aNumber, int32_t aMaxLevel,
   558                        int32_t aNumChildrenPerNode,
   559                        int32_t aFlags)
   560   {
   561     mLevel              = aLevel;
   562     mNumber             = aNumber;
   563     mTXMgr              = aTXMgr;
   564     mFlags              = aFlags & (~ALL_ERROR_FLAGS);
   565     mErrorFlags         = aFlags & ALL_ERROR_FLAGS;
   566     mTXMgr              = aTXMgr;
   567     mMaxLevel           = aMaxLevel;
   568     mNumChildrenPerNode = aNumChildrenPerNode;
   569   }
   571   nsITransactionManager *mTXMgr;
   573   int32_t mLevel;
   574   int32_t mNumber;
   575   int32_t mErrorFlags;
   577   int32_t mMaxLevel;
   578   int32_t mNumChildrenPerNode;
   580 public:
   582   AggregateTransaction(nsITransactionManager *aTXMgr,
   583                        int32_t aMaxLevel, int32_t aNumChildrenPerNode,
   584                        int32_t aFlags=NONE_FLAG)
   585   {
   586     mLevel              = 1;
   587     mNumber             = 1;
   588     mFlags              = aFlags & (~ALL_ERROR_FLAGS);
   589     mErrorFlags         = aFlags & ALL_ERROR_FLAGS;
   590     mTXMgr              = aTXMgr;
   591     mMaxLevel           = aMaxLevel;
   592     mNumChildrenPerNode = aNumChildrenPerNode;
   593   }
   595   virtual ~AggregateTransaction()
   596   {
   597     // printf("~AggregateTransaction(0x%.8x) - %3d (%3d)\n", this, mLevel, mVal);
   598   }
   600   NS_IMETHOD DoTransaction()
   601   {
   602     if (mLevel >= mMaxLevel) {
   603       // Only leaf nodes can throw errors!
   604       mFlags |= mErrorFlags;
   605     }
   607     nsresult result = SimpleTransaction::DoTransaction();
   609     if (NS_FAILED(result)) {
   610       // fail("QueryInterface() failed for transaction level %d. (%d)\n",
   611       //      mLevel, result);
   612       return result;
   613     }
   615     if (mLevel >= mMaxLevel)
   616       return NS_OK;
   618     if (mFlags & BATCH_FLAG) {
   619       result = mTXMgr->BeginBatch(nullptr);
   620       if (NS_FAILED(result)) {
   621         return result;
   622       }
   623     }
   625     int32_t cLevel = mLevel + 1;
   627     for (int i = 1; i <= mNumChildrenPerNode; i++) {
   628       int32_t flags = mErrorFlags & THROWS_DO_ERROR_FLAG;
   630       if ((mErrorFlags & THROWS_REDO_ERROR_FLAG) && i == mNumChildrenPerNode) {
   631         // Make the rightmost leaf transaction throw the error!
   632         flags = THROWS_REDO_ERROR_FLAG;
   633         mErrorFlags = mErrorFlags & (~THROWS_REDO_ERROR_FLAG);
   634       }
   635       else if ((mErrorFlags & THROWS_UNDO_ERROR_FLAG)
   636                && i == 1) {
   637         // Make the leftmost leaf transaction throw the error!
   638         flags = THROWS_UNDO_ERROR_FLAG;
   639         mErrorFlags = mErrorFlags & (~THROWS_UNDO_ERROR_FLAG);
   640       }
   642       flags |= mFlags & BATCH_FLAG;
   644       AggregateTransaction *tximpl =
   645               new AggregateTransaction(mTXMgr, cLevel, i, mMaxLevel,
   646                                        mNumChildrenPerNode, flags);
   648       if (!tximpl) {
   649         fail("Failed to allocate AggregateTransaction %d, level %d. (%d)\n",
   650              i, mLevel, result);
   652         if (mFlags & BATCH_FLAG)
   653           mTXMgr->EndBatch(false);
   655         return NS_ERROR_OUT_OF_MEMORY;
   656       }
   658       nsITransaction *tx = 0;
   659       result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
   660       if (NS_FAILED(result)) {
   661         fail("QueryInterface() failed for transaction %d, level %d. (%d)\n",
   662              i, mLevel, result);
   664         if (mFlags & BATCH_FLAG)
   665           mTXMgr->EndBatch(false);
   667         return result;
   668       }
   670       result = mTXMgr->DoTransaction(tx);
   672       if (NS_FAILED(result)) {
   673         // fail("Failed to execute transaction %d, level %d. (%d)\n",
   674         //      i, mLevel, result);
   675         tx->Release();
   677         if (mFlags & BATCH_FLAG)
   678           mTXMgr->EndBatch(false);
   680         return result;
   681       }
   683       tx->Release();
   684     }
   686     if (mFlags & BATCH_FLAG)
   687       mTXMgr->EndBatch(false);
   689     return result;
   690   }
   691 };
   693 class TestTransactionFactory
   694 {
   695 public:
   696   virtual TestTransaction *create(nsITransactionManager *txmgr, int32_t flags) = 0;
   697 };
   699 class SimpleTransactionFactory : public TestTransactionFactory
   700 {
   701 public:
   703   TestTransaction *create(nsITransactionManager *txmgr, int32_t flags)
   704   {
   705     return (TestTransaction *)new SimpleTransaction(flags);
   706   }
   707 };
   709 class AggregateTransactionFactory : public TestTransactionFactory
   710 {
   711 private:
   713   int32_t mMaxLevel;
   714   int32_t mNumChildrenPerNode;
   715   int32_t mFixedFlags;
   717 public:
   719   AggregateTransactionFactory(int32_t aMaxLevel, int32_t aNumChildrenPerNode,
   720                               int32_t aFixedFlags=NONE_FLAG)
   721       : mMaxLevel(aMaxLevel), mNumChildrenPerNode(aNumChildrenPerNode),
   722         mFixedFlags(aFixedFlags)
   723   {
   724   }
   726   virtual TestTransaction *create(nsITransactionManager *txmgr, int32_t flags)
   727   {
   728     return (TestTransaction *)new AggregateTransaction(txmgr, mMaxLevel,
   729                                                        mNumChildrenPerNode,
   730                                                        flags | mFixedFlags);
   731   }
   732 };
   734 void
   735 reset_globals()
   736 {
   737   sConstructorCount   = 0;
   739   sDestructorCount    = 0;
   740   sDestructorOrderArr = 0;
   742   sDoCount            = 0;
   743   sDoOrderArr         = 0;
   745   sUndoCount          = 0;
   746   sUndoOrderArr       = 0;
   748   sRedoCount          = 0;
   749   sRedoOrderArr       = 0;
   750 }
   752 /**
   753  * Test behaviors in non-batch mode.
   754  **/
   755 nsresult
   756 quick_test(TestTransactionFactory *factory)
   757 {
   758   nsresult result;
   760   /*******************************************************************
   761    *
   762    * Create a transaction manager implementation:
   763    *
   764    *******************************************************************/
   766   nsCOMPtr<nsITransactionManager> mgr =
   767     do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
   768   if (NS_FAILED(result) || !mgr) {
   769     fail("Failed to create Transaction Manager instance.\n");
   770     return NS_ERROR_OUT_OF_MEMORY;
   771   }
   773   passed("Create transaction manager instance");
   775   /*******************************************************************
   776    *
   777    * Call DoTransaction() with a null transaction:
   778    *
   779    *******************************************************************/
   781   result = mgr->DoTransaction(0);
   783   if (result != NS_ERROR_NULL_POINTER) {
   784     fail("DoTransaction() returned unexpected error. (%d)\n", result);
   785     return result;
   786   }
   788   passed("Call DoTransaction() with null transaction");
   790   /*******************************************************************
   791    *
   792    * Call UndoTransaction() with an empty undo stack:
   793    *
   794    *******************************************************************/
   796   result = mgr->UndoTransaction();
   798   if (NS_FAILED(result)) {
   799     fail("Undo on empty undo stack failed. (%d)\n", result);
   800     return result;
   801   }
   803   passed("Call UndoTransaction() with empty undo stack");
   805   /*******************************************************************
   806    *
   807    * Call RedoTransaction() with an empty redo stack:
   808    *
   809    *******************************************************************/
   811   result = mgr->RedoTransaction();
   813   if (NS_FAILED(result)) {
   814     fail("Redo on empty redo stack failed. (%d)\n", result);
   815     return result;
   816   }
   818   passed("Call RedoTransaction() with empty redo stack");
   820   /*******************************************************************
   821    *
   822    * Call SetMaxTransactionCount(-1) with empty undo and redo stacks:
   823    *
   824    *******************************************************************/
   826   result = mgr->SetMaxTransactionCount(-1);
   828   if (NS_FAILED(result)) {
   829     fail("SetMaxTransactionCount(-1) failed. (%d)\n", result);
   830     return result;
   831   }
   833   passed("Call SetMaxTransactionCount(-1) with empty undo and redo stacks");
   835   /*******************************************************************
   836    *
   837    * Call SetMaxTransactionCount(0) with empty undo and redo stacks:
   838    *
   839    *******************************************************************/
   841   result = mgr->SetMaxTransactionCount(0);
   843   if (NS_FAILED(result)) {
   844     fail("SetMaxTransactionCount(0) failed. (%d)\n", result);
   845     return result;
   846   }
   848   passed("Call SetMaxTransactionCount(0) with empty undo and redo stacks");
   850   /*******************************************************************
   851    *
   852    * Call SetMaxTransactionCount(10) with empty undo and redo stacks:
   853    *
   854    *******************************************************************/
   856   result = mgr->SetMaxTransactionCount(10);
   858   if (NS_FAILED(result)) {
   859     fail("SetMaxTransactionCount(10) failed. (%d)\n", result);
   860     return result;
   861   }
   863   passed("Call SetMaxTransactionCount(10) with empty undo and redo stacks");
   865   /*******************************************************************
   866    *
   867    * Call Clear() with empty undo and redo stacks:
   868    *
   869    *******************************************************************/
   871   result = mgr->Clear();
   872   if (NS_FAILED(result)) {
   873     fail("Clear on empty undo and redo stack failed. (%d)\n", result);
   874     return result;
   875   }
   877   passed("Call Clear() with empty undo and redo stack");
   879   int32_t numitems;
   881   /*******************************************************************
   882    *
   883    * Call GetNumberOfUndoItems() with an empty undo stack:
   884    *
   885    *******************************************************************/
   887   result = mgr->GetNumberOfUndoItems(&numitems);
   889   if (NS_FAILED(result)) {
   890     fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
   891          result);
   892     return result;
   893   }
   895   if (numitems != 0) {
   896     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
   897          numitems, result);
   898     return NS_ERROR_FAILURE;
   899   }
   901   passed("Call GetNumberOfUndoItems() with empty undo stack");
   903   /*******************************************************************
   904    *
   905    * Call GetNumberOfRedoItems() with an empty redo stack:
   906    *
   907    *******************************************************************/
   909   result = mgr->GetNumberOfRedoItems(&numitems);
   911   if (NS_FAILED(result)) {
   912     fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
   913          result);
   914     return result;
   915   }
   917   if (numitems != 0) {
   918     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
   919          numitems, result);
   920     return NS_ERROR_FAILURE;
   921   }
   923   passed("Call GetNumberOfRedoItems() with empty redo stack");
   925   nsITransaction *tx;
   927   /*******************************************************************
   928    *
   929    * Call PeekUndoStack() with an empty undo stack:
   930    *
   931    *******************************************************************/
   933   tx = 0;
   934   result = mgr->PeekUndoStack(&tx);
   936   TEST_TXMGR_IF_RELEASE(tx); // Don't hold onto any references!
   938   if (NS_FAILED(result)) {
   939     fail("PeekUndoStack() on empty undo stack failed. (%d)\n", result);
   940     return result;
   941   }
   943   if (tx != 0) {
   944     fail("PeekUndoStack() on empty undo stack failed. (%d)\n", result);
   945     return NS_ERROR_FAILURE;
   946   }
   948   passed("Call PeekUndoStack() with empty undo stack");
   950   /*******************************************************************
   951    *
   952    * Call PeekRedoStack() with an empty undo stack:
   953    *
   954    *******************************************************************/
   956   tx = 0;
   957   result = mgr->PeekRedoStack(&tx);
   959   TEST_TXMGR_IF_RELEASE(tx); // Don't hold onto any references!
   961   if (NS_FAILED(result)) {
   962     fail("PeekRedoStack() on empty redo stack failed. (%d)\n", result);
   963     return result;
   964   }
   966   if (tx != 0) {
   967     fail("PeekRedoStack() on empty redo stack failed. (%d)\n", result);
   968     return NS_ERROR_FAILURE;
   969   }
   971   passed("Call PeekRedoStack() with empty undo stack");
   973   /*******************************************************************
   974    *
   975    * Call AddListener() with a null listener pointer:
   976    *
   977    *******************************************************************/
   979   result = mgr->AddListener(0);
   981   if (result != NS_ERROR_NULL_POINTER) {
   982     fail("AddListener() returned unexpected error. (%d)\n", result);
   983     return result;
   984   }
   986   passed("Call AddListener() with null listener");
   988   /*******************************************************************
   989    *
   990    * Call RemoveListener() with a null listener pointer:
   991    *
   992    *******************************************************************/
   994   result = mgr->RemoveListener(0);
   996   if (result != NS_ERROR_NULL_POINTER) {
   997     fail("RemoveListener() returned unexpected error. (%d)\n", result);
   998     return result;
   999   }
  1001   passed("Call RemoveListener() with null listener");
  1003   int32_t i;
  1004   TestTransaction *tximpl;
  1005   nsITransaction *u1, *u2;
  1006   nsITransaction *r1, *r2;
  1008   /*******************************************************************
  1010    * Test coalescing by executing a transaction that can merge any
  1011    * command into itself. Then execute 20 transaction. Afterwards,
  1012    * we should still have the first transaction sitting on the undo
  1013    * stack. Then clear the undo and redo stacks.
  1015    *******************************************************************/
  1017   result = mgr->SetMaxTransactionCount(10);
  1019   if (NS_FAILED(result)) {
  1020     fail("SetMaxTransactionCount(10) failed. (%d)\n", result);
  1021     return result;
  1025   tximpl = factory->create(mgr, MERGE_FLAG);
  1027   if (!tximpl) {
  1028     fail("Failed to allocate initial transaction.\n");
  1029     return NS_ERROR_OUT_OF_MEMORY;
  1032   tx = 0;
  1034   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1036   if (NS_FAILED(result)) {
  1037     fail("QueryInterface() failed for initial transaction. (%d)\n",
  1038          result);
  1039     return result;
  1042   result = mgr->DoTransaction(tx);
  1044   if (NS_FAILED(result)) {
  1045     fail("Failed to execute initial transaction. (%d)\n", result);
  1046     return result;
  1049   tx->Release();
  1051   u1 = u2 = r1 = r2 = 0;
  1053   result = mgr->PeekUndoStack(&u1);
  1055   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1057   if (NS_FAILED(result)) {
  1058     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1059     return result;
  1062   if (u1 != tx) {
  1063     fail("Top of undo stack is different!. (%d)\n", result);
  1064     return NS_ERROR_FAILURE;
  1067   result = mgr->PeekRedoStack(&r1);
  1069   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1071   if (NS_FAILED(result)) {
  1072     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1073     return result;
  1076   for (i = 1; i <= 20; i++) {
  1077     tximpl = factory->create(mgr, NONE_FLAG);
  1079     if (!tximpl) {
  1080       fail("Failed to allocate transaction %d.\n", i);
  1081       return NS_ERROR_OUT_OF_MEMORY;
  1084     tx = 0;
  1085     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1086     if (NS_FAILED(result)) {
  1087       fail("QueryInterface() failed for transaction %d. (%d)\n",
  1088            i, result);
  1089       return result;
  1092     result = mgr->DoTransaction(tx);
  1093     if (NS_FAILED(result)) {
  1094       fail("Failed to execute transaction %d. (%d)\n", i, result);
  1095       return result;
  1098     tx->Release();
  1101   result = mgr->PeekUndoStack(&u2);
  1103   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1105   if (NS_FAILED(result)) {
  1106     fail("Second PeekUndoStack() failed. (%d)\n", result);
  1107     return result;
  1110   if (u1 != u2) {
  1111     fail("Top of undo stack changed. (%d)\n", result);
  1112     return NS_ERROR_FAILURE;
  1115   result = mgr->PeekRedoStack(&r2);
  1117   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1119   if (NS_FAILED(result)) {
  1120     fail("Second PeekRedoStack() failed. (%d)\n", result);
  1121     return result;
  1124   if (r1 != r2) {
  1125     fail("Top of redo stack changed. (%d)\n", result);
  1126     return NS_ERROR_FAILURE;
  1129   result = mgr->GetNumberOfUndoItems(&numitems);
  1131   if (NS_FAILED(result)) {
  1132     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  1133          result);
  1134     return result;
  1137   if (numitems != 1) {
  1138     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  1139          numitems, result);
  1140     return NS_ERROR_FAILURE;
  1143   result = mgr->GetNumberOfRedoItems(&numitems);
  1145   if (NS_FAILED(result)) {
  1146     fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1147          result);
  1148     return result;
  1151   if (numitems != 0) {
  1152     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1153          numitems, result);
  1154     return NS_ERROR_FAILURE;
  1157   result = mgr->Clear();
  1158   if (NS_FAILED(result)) {
  1159     fail("Clear() failed. (%d)\n", result);
  1160     return result;
  1163   passed("Test coalescing of transactions");
  1165   /*******************************************************************
  1167    * Execute 20 transactions. Afterwards, we should have 10
  1168    * transactions on the undo stack:
  1170    *******************************************************************/
  1172   for (i = 1; i <= 20; i++) {
  1173     tximpl = factory->create(mgr, NONE_FLAG);
  1175     if (!tximpl) {
  1176       fail("Failed to allocate transaction %d.\n", i);
  1177       return NS_ERROR_OUT_OF_MEMORY;
  1180     tx = 0;
  1181     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1182     if (NS_FAILED(result)) {
  1183       fail("QueryInterface() failed for transaction %d. (%d)\n",
  1184            i, result);
  1185       return result;
  1188     result = mgr->DoTransaction(tx);
  1189     if (NS_FAILED(result)) {
  1190       fail("Failed to execute transaction %d. (%d)\n", i, result);
  1191       return result;
  1194     tx->Release();
  1197   result = mgr->GetNumberOfUndoItems(&numitems);
  1199   if (NS_FAILED(result)) {
  1200     fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
  1201          result);
  1202     return result;
  1205   if (numitems != 10) {
  1206     fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  1207          numitems, result);
  1208     return NS_ERROR_FAILURE;
  1211   result = mgr->GetNumberOfRedoItems(&numitems);
  1213   if (NS_FAILED(result)) {
  1214     fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1215          result);
  1216     return result;
  1219   if (numitems != 0) {
  1220     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1221          numitems, result);
  1222     return NS_ERROR_FAILURE;
  1225   passed("Execute 20 transactions");
  1227   /*******************************************************************
  1229    * Execute 20 transient transactions. Afterwards, we should still
  1230    * have the same 10 transactions on the undo stack:
  1232    *******************************************************************/
  1234   u1 = u2 = r1 = r2 = 0;
  1236   result = mgr->PeekUndoStack(&u1);
  1238   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1240   if (NS_FAILED(result)) {
  1241     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1242     return result;
  1245   result = mgr->PeekRedoStack(&r1);
  1247   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1249   if (NS_FAILED(result)) {
  1250     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1251     return result;
  1254   for (i = 1; i <= 20; i++) {
  1255     tximpl = factory->create(mgr, TRANSIENT_FLAG);
  1257     if (!tximpl) {
  1258       fail("Failed to allocate transaction %d.\n", i);
  1259       return NS_ERROR_OUT_OF_MEMORY;
  1262     tx = 0;
  1263     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1264     if (NS_FAILED(result)) {
  1265       fail("QueryInterface() failed for transaction %d. (%d)\n",
  1266            i, result);
  1267       return result;
  1270     result = mgr->DoTransaction(tx);
  1271     if (NS_FAILED(result)) {
  1272       fail("Failed to execute transaction %d. (%d)\n", i, result);
  1273       return result;
  1276     tx->Release();
  1279   result = mgr->PeekUndoStack(&u2);
  1281   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1283   if (NS_FAILED(result)) {
  1284     fail("Second PeekUndoStack() failed. (%d)\n", result);
  1285     return result;
  1288   if (u1 != u2) {
  1289     fail("Top of undo stack changed. (%d)\n", result);
  1290     return NS_ERROR_FAILURE;
  1293   result = mgr->PeekRedoStack(&r2);
  1295   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1297   if (NS_FAILED(result)) {
  1298     fail("Second PeekRedoStack() failed. (%d)\n", result);
  1299     return result;
  1302   if (r1 != r2) {
  1303     fail("Top of redo stack changed. (%d)\n", result);
  1304     return NS_ERROR_FAILURE;
  1307   result = mgr->GetNumberOfUndoItems(&numitems);
  1309   if (NS_FAILED(result)) {
  1310     fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
  1311          result);
  1312     return result;
  1315   if (numitems != 10) {
  1316     fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  1317          numitems, result);
  1318     return NS_ERROR_FAILURE;
  1321   result = mgr->GetNumberOfRedoItems(&numitems);
  1323   if (NS_FAILED(result)) {
  1324     fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1325          result);
  1326     return result;
  1329   if (numitems != 0) {
  1330     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1331          numitems, result);
  1332     return NS_ERROR_FAILURE;
  1335   passed("Execute 20 transient transactions");
  1337   /*******************************************************************
  1339    * Undo 4 transactions. Afterwards, we should have 6 transactions
  1340    * on the undo stack, and 4 on the redo stack:
  1342    *******************************************************************/
  1344   for (i = 1; i <= 4; i++) {
  1345     result = mgr->UndoTransaction();
  1346     if (NS_FAILED(result)) {
  1347       fail("Failed to undo transaction %d. (%d)\n", i, result);
  1348       return result;
  1352   result = mgr->GetNumberOfUndoItems(&numitems);
  1354   if (NS_FAILED(result)) {
  1355     fail("GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
  1356          result);
  1357     return result;
  1360   if (numitems != 6) {
  1361     fail("GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
  1362          numitems, result);
  1363     return NS_ERROR_FAILURE;
  1366   result = mgr->GetNumberOfRedoItems(&numitems);
  1368   if (NS_FAILED(result)) {
  1369     fail("GetNumberOfRedoItems() on redo stack with 4 items failed. (%d)\n",
  1370          result);
  1371     return result;
  1374   if (numitems != 4) {
  1375     fail("GetNumberOfRedoItems() expected 4 got %d. (%d)\n",
  1376          numitems, result);
  1377     return NS_ERROR_FAILURE;
  1380   passed("Undo 4 transactions");
  1382   /*******************************************************************
  1384    * Redo 2 transactions. Afterwards, we should have 8 transactions
  1385    * on the undo stack, and 2 on the redo stack:
  1387    *******************************************************************/
  1389   for (i = 1; i <= 2; ++i) {
  1390     result = mgr->RedoTransaction();
  1391     if (NS_FAILED(result)) {
  1392       fail("Failed to redo transaction %d. (%d)\n", i, result);
  1393       return result;
  1397   result = mgr->GetNumberOfUndoItems(&numitems);
  1399   if (NS_FAILED(result)) {
  1400     fail("GetNumberOfUndoItems() on undo stack with 8 items failed. (%d)\n",
  1401          result);
  1402     return result;
  1405   if (numitems != 8) {
  1406     fail("GetNumberOfUndoItems() expected 8 got %d. (%d)\n",
  1407          numitems, result);
  1408     return NS_ERROR_FAILURE;
  1411   result = mgr->GetNumberOfRedoItems(&numitems);
  1413   if (NS_FAILED(result)) {
  1414     fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
  1415          result);
  1416     return result;
  1419   if (numitems != 2) {
  1420     fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
  1421          numitems, result);
  1422     return NS_ERROR_FAILURE;
  1425   passed("Redo 2 transactions");
  1427   /*******************************************************************
  1429    * Execute a new transaction. The redo stack should get pruned!
  1431    *******************************************************************/
  1433   tximpl = factory->create(mgr, NONE_FLAG);
  1435   if (!tximpl) {
  1436     fail("Failed to allocate transaction.\n");
  1437     return NS_ERROR_OUT_OF_MEMORY;
  1440   tx = 0;
  1442   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1444   if (NS_FAILED(result)) {
  1445     fail("QueryInterface() failed for transaction. (%d)\n", result);
  1446     return result;
  1449   result = mgr->DoTransaction(tx);
  1450   if (NS_FAILED(result)) {
  1451     fail("Failed to execute transaction. (%d)\n", result);
  1452     return result;
  1455   tx->Release();
  1457   result = mgr->GetNumberOfUndoItems(&numitems);
  1459   if (NS_FAILED(result)) {
  1460     fail("GetNumberOfUndoItems() on undo stack with 9 items failed. (%d)\n",
  1461          result);
  1462     return result;
  1465   if (numitems != 9) {
  1466     fail("GetNumberOfUndoItems() expected 9 got %d. (%d)\n",
  1467          numitems, result);
  1468     return NS_ERROR_FAILURE;
  1471   result = mgr->GetNumberOfRedoItems(&numitems);
  1473   if (NS_FAILED(result)) {
  1474     fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1475          result);
  1476     return result;
  1479   if (numitems != 0) {
  1480     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1481          numitems, result);
  1482     return NS_ERROR_FAILURE;
  1485   passed("Check if new transactions prune the redo stack");
  1487   /*******************************************************************
  1489    * Undo 4 transactions then clear the undo and redo stacks.
  1491    *******************************************************************/
  1493   for (i = 1; i <= 4; ++i) {
  1494     result = mgr->UndoTransaction();
  1495     if (NS_FAILED(result)) {
  1496       fail("Failed to undo transaction %d. (%d)\n", i, result);
  1497       return result;
  1501   result = mgr->GetNumberOfUndoItems(&numitems);
  1503   if (NS_FAILED(result)) {
  1504     fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
  1505          result);
  1506     return result;
  1509   if (numitems != 5) {
  1510     fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
  1511          numitems, result);
  1512     return NS_ERROR_FAILURE;
  1515   result = mgr->GetNumberOfRedoItems(&numitems);
  1517   if (NS_FAILED(result)) {
  1518     fail("GetNumberOfRedoItems() on redo stack with 4 items failed. (%d)\n",
  1519          result);
  1520     return result;
  1523   if (numitems != 4) {
  1524     fail("GetNumberOfRedoItems() expected 4 got %d. (%d)\n",
  1525          numitems, result);
  1526     return NS_ERROR_FAILURE;
  1529   result = mgr->Clear();
  1530   if (NS_FAILED(result)) {
  1531     fail("Clear() failed. (%d)\n", result);
  1532     return result;
  1535   result = mgr->GetNumberOfUndoItems(&numitems);
  1537   if (NS_FAILED(result)) {
  1538     fail("GetNumberOfUndoItems() on cleared undo stack failed. (%d)\n",
  1539          result);
  1540     return result;
  1543   if (numitems != 0) {
  1544     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  1545          numitems, result);
  1546     return NS_ERROR_FAILURE;
  1549   result = mgr->GetNumberOfRedoItems(&numitems);
  1551   if (NS_FAILED(result)) {
  1552     fail("GetNumberOfRedoItems() on cleared redo stack failed. (%d)\n",
  1553          result);
  1554     return result;
  1557   if (numitems != 0) {
  1558     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1559          numitems, result);
  1560     return NS_ERROR_FAILURE;
  1563   passed("Undo 4 transactions then clear the undo and redo stacks");
  1565   /*******************************************************************
  1567    * Execute 5 transactions.
  1569    *******************************************************************/
  1571   for (i = 1; i <= 5; i++) {
  1572     tximpl = factory->create(mgr, NONE_FLAG);
  1574     if (!tximpl) {
  1575       fail("Failed to allocate transaction %d.\n", i);
  1576       return NS_ERROR_OUT_OF_MEMORY;
  1579     tx = 0;
  1580     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1581     if (NS_FAILED(result)) {
  1582       fail("QueryInterface() failed for transaction %d. (%d)\n",
  1583            i, result);
  1584       return result;
  1587     result = mgr->DoTransaction(tx);
  1588     if (NS_FAILED(result)) {
  1589       fail("Failed to execute transaction %d. (%d)\n", i, result);
  1590       return result;
  1593     tx->Release();
  1596   result = mgr->GetNumberOfUndoItems(&numitems);
  1598   if (NS_FAILED(result)) {
  1599     fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
  1600          result);
  1601     return result;
  1604   if (numitems != 5) {
  1605     fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
  1606          numitems, result);
  1607     return NS_ERROR_FAILURE;
  1610   result = mgr->GetNumberOfRedoItems(&numitems);
  1612   if (NS_FAILED(result)) {
  1613     fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  1614          result);
  1615     return result;
  1618   if (numitems != 0) {
  1619     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1620          numitems, result);
  1621     return NS_ERROR_FAILURE;
  1624   passed("Execute 5 transactions");
  1626   /*******************************************************************
  1628    * Test transaction DoTransaction() error:
  1630    *******************************************************************/
  1632   tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
  1634   if (!tximpl) {
  1635     fail("Failed to allocate transaction.\n");
  1636     return NS_ERROR_OUT_OF_MEMORY;
  1639   tx = 0;
  1641   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1643   if (NS_FAILED(result)) {
  1644     fail("QueryInterface() failed for transaction. (%d)\n", result);
  1645     return result;
  1648   u1 = u2 = r1 = r2 = 0;
  1650   result = mgr->PeekUndoStack(&u1);
  1652   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1654   if (NS_FAILED(result)) {
  1655     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1656     return result;
  1659   result = mgr->PeekRedoStack(&r1);
  1661   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1663   if (NS_FAILED(result)) {
  1664     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1665     return result;
  1668   result = mgr->DoTransaction(tx);
  1670   if (result != NS_ERROR_FAILURE) {
  1671     fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1672     return result;
  1675   tx->Release();
  1677   result = mgr->PeekUndoStack(&u2);
  1679   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1681   if (NS_FAILED(result)) {
  1682     fail("Second PeekUndoStack() failed. (%d)\n", result);
  1683     return result;
  1686   if (u1 != u2) {
  1687     fail("Top of undo stack changed. (%d)\n", result);
  1688     return NS_ERROR_FAILURE;
  1691   result = mgr->PeekRedoStack(&r2);
  1693   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1695   if (NS_FAILED(result)) {
  1696     fail("Second PeekRedoStack() failed. (%d)\n", result);
  1697     return result;
  1700   if (r1 != r2) {
  1701     fail("Top of redo stack changed. (%d)\n", result);
  1702     return NS_ERROR_FAILURE;
  1705   result = mgr->GetNumberOfUndoItems(&numitems);
  1707   if (NS_FAILED(result)) {
  1708     fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
  1709          result);
  1710     return result;
  1713   if (numitems != 5) {
  1714     fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
  1715          numitems, result);
  1716     return NS_ERROR_FAILURE;
  1719   result = mgr->GetNumberOfRedoItems(&numitems);
  1721   if (NS_FAILED(result)) {
  1722     fail("GetNumberOfRedoItems() on empty redo stack. (%d)\n",
  1723          result);
  1724     return result;
  1727   if (numitems != 0) {
  1728     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1729          numitems, result);
  1730     return NS_ERROR_FAILURE;
  1733   passed("Test transaction DoTransaction() error");
  1735   /*******************************************************************
  1737    * Test transaction UndoTransaction() error:
  1739    *******************************************************************/
  1741   tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
  1743   if (!tximpl) {
  1744     fail("Failed to allocate transaction.\n");
  1745     return NS_ERROR_OUT_OF_MEMORY;
  1748   tx = 0;
  1750   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1752   if (NS_FAILED(result)) {
  1753     fail("QueryInterface() failed for transaction. (%d)\n", result);
  1754     return result;
  1757   result = mgr->DoTransaction(tx);
  1759   if (NS_FAILED(result)) {
  1760     fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1761     return result;
  1764   tx->Release();
  1766   u1 = u2 = r1 = r2 = 0;
  1768   result = mgr->PeekUndoStack(&u1);
  1770   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1772   if (NS_FAILED(result)) {
  1773     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1774     return result;
  1777   result = mgr->PeekRedoStack(&r1);
  1779   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1781   if (NS_FAILED(result)) {
  1782     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1783     return result;
  1786   result = mgr->UndoTransaction();
  1788   if (result != NS_ERROR_FAILURE) {
  1789     fail("UndoTransaction() returned unexpected error. (%d)\n", result);
  1790     return result;
  1793   result = mgr->PeekUndoStack(&u2);
  1795   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1797   if (NS_FAILED(result)) {
  1798     fail("Second PeekUndoStack() failed. (%d)\n", result);
  1799     return result;
  1802   if (u1 != u2) {
  1803     fail("Top of undo stack changed. (%d)\n", result);
  1804     return NS_ERROR_FAILURE;
  1807   result = mgr->PeekRedoStack(&r2);
  1809   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1811   if (NS_FAILED(result)) {
  1812     fail("Second PeekRedoStack() failed. (%d)\n", result);
  1813     return result;
  1816   if (r1 != r2) {
  1817     fail("Top of redo stack changed. (%d)\n", result);
  1818     return NS_ERROR_FAILURE;
  1821   result = mgr->GetNumberOfUndoItems(&numitems);
  1823   if (NS_FAILED(result)) {
  1824     fail("GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
  1825          result);
  1826     return result;
  1829   if (numitems != 6) {
  1830     fail("GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
  1831          numitems, result);
  1832     return NS_ERROR_FAILURE;
  1835   result = mgr->GetNumberOfRedoItems(&numitems);
  1837   if (NS_FAILED(result)) {
  1838     fail("GetNumberOfRedoItems() on empty redo stack. (%d)\n",
  1839          result);
  1840     return result;
  1843   if (numitems != 0) {
  1844     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  1845          numitems, result);
  1846     return NS_ERROR_FAILURE;
  1849   passed("Test transaction UndoTransaction() error");
  1851   /*******************************************************************
  1853    * Test transaction RedoTransaction() error:
  1855    *******************************************************************/
  1857   tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
  1859   if (!tximpl) {
  1860     fail("Failed to allocate transaction.\n");
  1861     return NS_ERROR_OUT_OF_MEMORY;
  1864   tx = 0;
  1866   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1868   if (NS_FAILED(result)) {
  1869     fail("QueryInterface() failed for RedoErrorTransaction. (%d)\n",
  1870          result);
  1871     return result;
  1874   result = mgr->DoTransaction(tx);
  1876   if (NS_FAILED(result)) {
  1877     fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1878     return result;
  1881   tx->Release();
  1883   //
  1884   // Execute a normal transaction to be used in a later test:
  1885   //
  1887   tximpl = factory->create(mgr, NONE_FLAG);
  1889   if (!tximpl) {
  1890     fail("Failed to allocate transaction.\n");
  1891     return NS_ERROR_OUT_OF_MEMORY;
  1894   tx = 0;
  1896   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  1898   if (NS_FAILED(result)) {
  1899     fail("QueryInterface() failed for transaction. (%d)\n", result);
  1900     return result;
  1903   result = mgr->DoTransaction(tx);
  1905   if (NS_FAILED(result)) {
  1906     fail("DoTransaction() returned unexpected error. (%d)\n", result);
  1907     return result;
  1910   tx->Release();
  1912   //
  1913   // Undo the 2 transactions just executed.
  1914   //
  1916   for (i = 1; i <= 2; ++i) {
  1917     result = mgr->UndoTransaction();
  1918     if (NS_FAILED(result)) {
  1919       fail("Failed to undo transaction %d. (%d)\n", i, result);
  1920       return result;
  1924   //
  1925   // The RedoErrorTransaction should now be at the top of the redo stack!
  1926   //
  1928   u1 = u2 = r1 = r2 = 0;
  1930   result = mgr->PeekUndoStack(&u1);
  1932   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  1934   if (NS_FAILED(result)) {
  1935     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  1936     return result;
  1939   result = mgr->PeekRedoStack(&r1);
  1941   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  1943   if (NS_FAILED(result)) {
  1944     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  1945     return result;
  1948   result = mgr->RedoTransaction();
  1950   if (result != NS_ERROR_FAILURE) {
  1951     fail("RedoTransaction() returned unexpected error. (%d)\n", result);
  1952     return result;
  1955   result = mgr->PeekUndoStack(&u2);
  1957   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  1959   if (NS_FAILED(result)) {
  1960     fail("Second PeekUndoStack() failed. (%d)\n", result);
  1961     return result;
  1964   if (u1 != u2) {
  1965     fail("Top of undo stack changed. (%d)\n", result);
  1966     return NS_ERROR_FAILURE;
  1969   result = mgr->PeekRedoStack(&r2);
  1971   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  1973   if (NS_FAILED(result)) {
  1974     fail("Second PeekRedoStack() failed. (%d)\n", result);
  1975     return result;
  1978   if (r1 != r2) {
  1979     fail("Top of redo stack changed. (%d)\n", result);
  1980     return NS_ERROR_FAILURE;
  1983   result = mgr->GetNumberOfUndoItems(&numitems);
  1985   if (NS_FAILED(result)) {
  1986     fail("GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
  1987          result);
  1988     return result;
  1991   if (numitems != 6) {
  1992     fail("GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
  1993          numitems, result);
  1994     return NS_ERROR_FAILURE;
  1997   result = mgr->GetNumberOfRedoItems(&numitems);
  1999   if (NS_FAILED(result)) {
  2000     fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
  2001          result);
  2002     return result;
  2005   if (numitems != 2) {
  2006     fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
  2007          numitems, result);
  2008     return NS_ERROR_FAILURE;
  2011   passed("Test transaction RedoTransaction() error");
  2013   /*******************************************************************
  2015    * Make sure that setting the transaction manager's max transaction
  2016    * count to zero, clears both the undo and redo stacks, and executes
  2017    * all new commands without pushing them on the undo stack!
  2019    *******************************************************************/
  2021   result = mgr->SetMaxTransactionCount(0);
  2023   if (NS_FAILED(result)) {
  2024     fail("SetMaxTransactionCount(0) failed. (%d)\n", result);
  2025     return result;
  2028   result = mgr->GetNumberOfUndoItems(&numitems);
  2030   if (NS_FAILED(result)) {
  2031     fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  2032          result);
  2033     return result;
  2036   if (numitems != 0) {
  2037     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  2038          numitems, result);
  2039     return NS_ERROR_FAILURE;
  2042   result = mgr->GetNumberOfRedoItems(&numitems);
  2044   if (NS_FAILED(result)) {
  2045     fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  2046          result);
  2047     return result;
  2050   if (numitems != 0) {
  2051     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  2052          numitems, result);
  2053     return NS_ERROR_FAILURE;
  2056   for (i = 1; i <= 20; i++) {
  2057     tximpl = factory->create(mgr, NONE_FLAG);
  2059     if (!tximpl) {
  2060       fail("Failed to allocate transaction %d.\n", i);
  2061       return NS_ERROR_OUT_OF_MEMORY;
  2064     tx = 0;
  2065     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  2066     if (NS_FAILED(result)) {
  2067       fail("QueryInterface() failed for transaction %d. (%d)\n",
  2068            i, result);
  2069       return result;
  2072     result = mgr->DoTransaction(tx);
  2073     if (NS_FAILED(result)) {
  2074       fail("Failed to execute transaction %d. (%d)\n", i, result);
  2075       return result;
  2078     tx->Release();
  2080     result = mgr->GetNumberOfUndoItems(&numitems);
  2082     if (NS_FAILED(result)) {
  2083       fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  2084            result);
  2085       return result;
  2088     if (numitems != 0) {
  2089       fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  2090            numitems, result);
  2091       return NS_ERROR_FAILURE;
  2094     result = mgr->GetNumberOfRedoItems(&numitems);
  2096     if (NS_FAILED(result)) {
  2097       fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  2098            result);
  2099       return result;
  2102     if (numitems != 0) {
  2103       fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  2104            numitems, result);
  2105       return NS_ERROR_FAILURE;
  2109   passed("Test max transaction count of zero");
  2111   /*******************************************************************
  2113    * Make sure that setting the transaction manager's max transaction
  2114    * count to something greater than the number of transactions on
  2115    * both the undo and redo stacks causes no pruning of the stacks:
  2117    *******************************************************************/
  2119   result = mgr->SetMaxTransactionCount(-1);
  2121   if (NS_FAILED(result)) {
  2122     fail("SetMaxTransactionCount(-1) failed. (%d)\n", result);
  2123     return result;
  2126   // Push 20 transactions on the undo stack:
  2128   for (i = 1; i <= 20; i++) {
  2129     tximpl = factory->create(mgr, NONE_FLAG);
  2131     if (!tximpl) {
  2132       fail("Failed to allocate transaction %d.\n", i);
  2133       return NS_ERROR_OUT_OF_MEMORY;
  2136     tx = 0;
  2137     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  2138     if (NS_FAILED(result)) {
  2139       fail("QueryInterface() failed for transaction %d. (%d)\n",
  2140            i, result);
  2141       return result;
  2144     result = mgr->DoTransaction(tx);
  2145     if (NS_FAILED(result)) {
  2146       fail("Failed to execute transaction %d. (%d)\n", i, result);
  2147       return result;
  2150     tx->Release();
  2152     result = mgr->GetNumberOfUndoItems(&numitems);
  2154     if (NS_FAILED(result)) {
  2155       fail("GetNumberOfUndoItems() on undo stack with %d items failed. (%d)\n",
  2156            i, result);
  2157       return result;
  2160     if (numitems != i) {
  2161       fail("GetNumberOfUndoItems() expected %d got %d. (%d)\n",
  2162            i, numitems, result);
  2163       return NS_ERROR_FAILURE;
  2166     result = mgr->GetNumberOfRedoItems(&numitems);
  2168     if (NS_FAILED(result)) {
  2169       fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  2170            result);
  2171       return result;
  2174     if (numitems != 0) {
  2175       fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  2176            numitems, result);
  2177       return NS_ERROR_FAILURE;
  2181   for (i = 1; i <= 10; i++) {
  2183     result = mgr->UndoTransaction();
  2184     if (NS_FAILED(result)) {
  2185       fail("Failed to undo transaction %d. (%d)\n", i, result);
  2186       return result;
  2189   result = mgr->GetNumberOfUndoItems(&numitems);
  2191   if (NS_FAILED(result)) {
  2192     fail("GetNumberOfUndoItems() on empty undo stack with 10 items failed. (%d)\n",
  2193          result);
  2194     return result;
  2197   if (numitems != 10) {
  2198     fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  2199          numitems, result);
  2200     return NS_ERROR_FAILURE;
  2203   result = mgr->GetNumberOfRedoItems(&numitems);
  2205   if (NS_FAILED(result)) {
  2206     fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
  2207          result);
  2208     return result;
  2211   if (numitems != 10) {
  2212     fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
  2213          numitems, result);
  2214     return NS_ERROR_FAILURE;
  2217   u1 = u2 = r1 = r2 = 0;
  2219   result = mgr->PeekUndoStack(&u1);
  2221   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  2223   if (NS_FAILED(result)) {
  2224     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  2225     return result;
  2228   result = mgr->PeekRedoStack(&r1);
  2230   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  2232   if (NS_FAILED(result)) {
  2233     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  2234     return result;
  2237   result = mgr->SetMaxTransactionCount(25);
  2239   if (NS_FAILED(result)) {
  2240     fail("SetMaxTransactionCount(25) failed. (%d)\n", result);
  2241     return result;
  2244   result = mgr->PeekUndoStack(&u2);
  2246   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  2248   if (NS_FAILED(result)) {
  2249     fail("Second PeekUndoStack() failed. (%d)\n", result);
  2250     return result;
  2253   if (u1 != u2) {
  2254     fail("Top of undo stack changed. (%d)\n", result);
  2255     return NS_ERROR_FAILURE;
  2258   result = mgr->PeekRedoStack(&r2);
  2260   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  2262   if (NS_FAILED(result)) {
  2263     fail("Second PeekRedoStack() failed. (%d)\n", result);
  2264     return result;
  2267   if (r1 != r2) {
  2268     fail("Top of redo stack changed. (%d)\n", result);
  2269     return NS_ERROR_FAILURE;
  2272   result = mgr->GetNumberOfUndoItems(&numitems);
  2274   if (NS_FAILED(result)) {
  2275     fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
  2276          result);
  2277     return result;
  2280   if (numitems != 10) {
  2281     fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  2282          numitems, result);
  2283     return NS_ERROR_FAILURE;
  2286   result = mgr->GetNumberOfRedoItems(&numitems);
  2288   if (NS_FAILED(result)) {
  2289     fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
  2290          result);
  2291     return result;
  2294   if (numitems != 10) {
  2295     fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
  2296          numitems, result);
  2297     return NS_ERROR_FAILURE;
  2300   passed("Test SetMaxTransactionCount() greater than num stack items");
  2302   /*******************************************************************
  2304    * Test undo stack pruning by setting the transaction
  2305    * manager's max transaction count to a number lower than the
  2306    * number of transactions on both the undo and redo stacks:
  2308    *******************************************************************/
  2310   u1 = u2 = r1 = r2 = 0;
  2312   result = mgr->PeekUndoStack(&u1);
  2314   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  2316   if (NS_FAILED(result)) {
  2317     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  2318     return result;
  2321   result = mgr->PeekRedoStack(&r1);
  2323   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  2325   if (NS_FAILED(result)) {
  2326     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  2327     return result;
  2330   result = mgr->SetMaxTransactionCount(15);
  2332   if (NS_FAILED(result)) {
  2333     fail("SetMaxTransactionCount(15) failed. (%d)\n", result);
  2334     return result;
  2337   result = mgr->PeekUndoStack(&u2);
  2339   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  2341   if (NS_FAILED(result)) {
  2342     fail("Second PeekUndoStack() failed. (%d)\n", result);
  2343     return result;
  2346   if (u1 != u2) {
  2347     fail("Top of undo stack changed. (%d)\n", result);
  2348     return NS_ERROR_FAILURE;
  2351   result = mgr->PeekRedoStack(&r2);
  2353   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  2355   if (NS_FAILED(result)) {
  2356     fail("Second PeekRedoStack() failed. (%d)\n", result);
  2357     return result;
  2360   if (r1 != r2) {
  2361     fail("Top of redo stack changed. (%d)\n", result);
  2362     return NS_ERROR_FAILURE;
  2365   result = mgr->GetNumberOfUndoItems(&numitems);
  2367   if (NS_FAILED(result)) {
  2368     fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
  2369            result);
  2370     return result;
  2373   if (numitems != 5) {
  2374     fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
  2375          numitems, result);
  2376     return NS_ERROR_FAILURE;
  2379   result = mgr->GetNumberOfRedoItems(&numitems);
  2381   if (NS_FAILED(result)) {
  2382     fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
  2383          result);
  2384     return result;
  2387   if (numitems != 10) {
  2388     fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
  2389          numitems, result);
  2390     return NS_ERROR_FAILURE;
  2393   passed("Test SetMaxTransactionCount() pruning undo stack");
  2395   /*******************************************************************
  2397    * Test redo stack pruning by setting the transaction
  2398    * manager's max transaction count to a number lower than the
  2399    * number of transactions on both the undo and redo stacks:
  2401    *******************************************************************/
  2403   u1 = u2 = r1 = r2 = 0;
  2405   result = mgr->PeekUndoStack(&u1);
  2407   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  2409   if (NS_FAILED(result)) {
  2410     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  2411     return result;
  2414   result = mgr->PeekRedoStack(&r1);
  2416   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  2418   if (NS_FAILED(result)) {
  2419     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  2420     return result;
  2423   result = mgr->SetMaxTransactionCount(5);
  2425   if (NS_FAILED(result)) {
  2426     fail("SetMaxTransactionCount(5) failed. (%d)\n", result);
  2427     return result;
  2430   result = mgr->PeekUndoStack(&u2);
  2432   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  2434   if (NS_FAILED(result)) {
  2435     fail("Second PeekUndoStack() failed. (%d)\n", result);
  2436     return result;
  2439   if (u2) {
  2440     fail("Unexpected item at top of undo stack. (%d)\n", result);
  2441     return NS_ERROR_FAILURE;
  2444   result = mgr->PeekRedoStack(&r2);
  2446   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  2448   if (NS_FAILED(result)) {
  2449     fail("Second PeekRedoStack() failed. (%d)\n", result);
  2450     return result;
  2453   if (r1 != r2) {
  2454     fail("Top of redo stack changed. (%d)\n", result);
  2455     return NS_ERROR_FAILURE;
  2458   result = mgr->GetNumberOfUndoItems(&numitems);
  2460   if (NS_FAILED(result)) {
  2461     fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  2462          result);
  2463     return result;
  2466   if (numitems != 0) {
  2467     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  2468          numitems, result);
  2469     return NS_ERROR_FAILURE;
  2472   result = mgr->GetNumberOfRedoItems(&numitems);
  2474   if (NS_FAILED(result)) {
  2475     fail("GetNumberOfRedoItems() on redo stack with 5 items failed. (%d)\n",
  2476          result);
  2477     return result;
  2480   if (numitems != 5) {
  2481     fail("GetNumberOfRedoItems() expected 5 got %d. (%d)\n",
  2482          numitems, result);
  2483     return NS_ERROR_FAILURE;
  2486   passed("Test SetMaxTransactionCount() pruning redo stack");
  2488   /*******************************************************************
  2490    * Release the transaction manager. Any transactions on the undo
  2491    * and redo stack should automatically be released:
  2493    *******************************************************************/
  2495   result = mgr->SetMaxTransactionCount(-1);
  2497   if (NS_FAILED(result)) {
  2498     fail("SetMaxTransactionCount(-1) failed. (%d)\n", result);
  2499     return result;
  2502   // Push 20 transactions on the undo stack:
  2504   for (i = 1; i <= 20; i++) {
  2505     tximpl = factory->create(mgr, NONE_FLAG);
  2507     if (!tximpl) {
  2508       fail("Failed to allocate transaction %d.\n", i);
  2509       return NS_ERROR_OUT_OF_MEMORY;
  2512     tx = 0;
  2513     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  2514     if (NS_FAILED(result)) {
  2515       fail("QueryInterface() failed for transaction %d. (%d)\n",
  2516            i, result);
  2517       return result;
  2520     result = mgr->DoTransaction(tx);
  2521     if (NS_FAILED(result)) {
  2522       fail("Failed to execute transaction %d. (%d)\n", i, result);
  2523       return result;
  2526     tx->Release();
  2528     result = mgr->GetNumberOfUndoItems(&numitems);
  2530     if (NS_FAILED(result)) {
  2531       fail("GetNumberOfUndoItems() on undo stack with %d items failed. (%d)\n",
  2532            i, result);
  2533       return result;
  2536     if (numitems != i) {
  2537       fail("GetNumberOfUndoItems() expected %d got %d. (%d)\n",
  2538            i, numitems, result);
  2539       return NS_ERROR_FAILURE;
  2542     result = mgr->GetNumberOfRedoItems(&numitems);
  2544     if (NS_FAILED(result)) {
  2545       fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  2546            result);
  2547       return result;
  2550     if (numitems != 0) {
  2551       fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  2552            numitems, result);
  2553       return NS_ERROR_FAILURE;
  2557   for (i = 1; i <= 10; i++) {
  2559     result = mgr->UndoTransaction();
  2560     if (NS_FAILED(result)) {
  2561       fail("Failed to undo transaction %d. (%d)\n", i, result);
  2562       return result;
  2565   result = mgr->GetNumberOfUndoItems(&numitems);
  2567   if (NS_FAILED(result)) {
  2568     fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
  2569          result);
  2570     return result;
  2573   if (numitems != 10) {
  2574     fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  2575          numitems, result);
  2576     return NS_ERROR_FAILURE;
  2579   result = mgr->GetNumberOfRedoItems(&numitems);
  2581   if (NS_FAILED(result)) {
  2582     fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
  2583          result);
  2584     return result;
  2587   if (numitems != 10) {
  2588     fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
  2589          numitems, result);
  2590     return NS_ERROR_FAILURE;
  2593   result = mgr->Clear();
  2594   if (NS_FAILED(result)) {
  2595     fail("Clear() failed. (%d)\n", result);
  2596     return result;
  2599   passed("Release the transaction manager");
  2601   /*******************************************************************
  2603    * Make sure number of transactions created matches number of
  2604    * transactions destroyed!
  2606    *******************************************************************/
  2608   /* Disabled because the current cycle collector doesn't delete
  2609      cycle collectable objects synchronously.
  2610   if (sConstructorCount != sDestructorCount) {
  2611     fail("Transaction constructor count (%d) != destructor count (%d).\n",
  2612          sConstructorCount, sDestructorCount);
  2613     return NS_ERROR_FAILURE;
  2614   }*/
  2616   passed("Number of transactions created and destroyed match");
  2617   passed("%d transactions processed during quick test", sConstructorCount);
  2619   return NS_OK;
  2622 nsresult
  2623 simple_test()
  2625   /*******************************************************************
  2627    * Initialize globals for test.
  2629    *******************************************************************/
  2630   reset_globals();
  2631   sDestructorOrderArr = sSimpleTestDestructorOrderArr;
  2632   sDoOrderArr         = sSimpleTestDoOrderArr;
  2633   sUndoOrderArr       = sSimpleTestUndoOrderArr;
  2634   sRedoOrderArr       = sSimpleTestRedoOrderArr;
  2636   /*******************************************************************
  2638    * Run the quick test.
  2640    *******************************************************************/
  2642   printf("\n-----------------------------------------------------\n");
  2643   printf("- Begin Simple Transaction Test:\n");
  2644   printf("-----------------------------------------------------\n");
  2646   SimpleTransactionFactory factory;
  2648   return quick_test(&factory);
  2651 nsresult
  2652 aggregation_test()
  2654   /*******************************************************************
  2656    * Initialize globals for test.
  2658    *******************************************************************/
  2660   reset_globals();
  2661   sDestructorOrderArr = sAggregateTestDestructorOrderArr;
  2662   sDoOrderArr         = sAggregateTestDoOrderArr;
  2663   sUndoOrderArr       = sAggregateTestUndoOrderArr;
  2664   sRedoOrderArr       = sAggregateTestRedoOrderArr;
  2666   /*******************************************************************
  2668    * Run the quick test.
  2670    *******************************************************************/
  2672   printf("\n-----------------------------------------------------\n");
  2673   printf("- Begin Aggregate Transaction Test:\n");
  2674   printf("-----------------------------------------------------\n");
  2676   AggregateTransactionFactory factory(3, 2);
  2678   return quick_test(&factory);
  2681 /**
  2682  * Test behaviors in batch mode.
  2683  **/
  2684 nsresult
  2685 quick_batch_test(TestTransactionFactory *factory)
  2687   nsresult result;
  2689   /*******************************************************************
  2691    * Create a transaction manager implementation:
  2693    *******************************************************************/
  2695   nsCOMPtr<nsITransactionManager> mgr =
  2696     do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
  2697   if (NS_FAILED(result) || !mgr) {
  2698     fail("Failed to create Transaction Manager instance.\n");
  2699     return NS_ERROR_OUT_OF_MEMORY;
  2702   passed("Create transaction manager instance");
  2704   int32_t numitems;
  2706   /*******************************************************************
  2708    * Make sure an unbalanced call to EndBatch(false) with empty undo stack
  2709    * throws an error!
  2711    *******************************************************************/
  2713   result = mgr->GetNumberOfUndoItems(&numitems);
  2715   if (NS_FAILED(result)) {
  2716     fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  2717          result);
  2718     return result;
  2721   if (numitems != 0) {
  2722     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  2723          numitems, result);
  2724     return NS_ERROR_FAILURE;
  2727   result = mgr->EndBatch(false);
  2729   if (result != NS_ERROR_FAILURE) {
  2730     fail("EndBatch(false) returned unexpected status. (%d)\n", result);
  2731     return result;
  2734   result = mgr->GetNumberOfUndoItems(&numitems);
  2736   if (NS_FAILED(result)) {
  2737     fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  2738          result);
  2739     return result;
  2742   if (numitems != 0) {
  2743     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  2744          numitems, result);
  2745     return NS_ERROR_FAILURE;
  2748   passed("Test unbalanced EndBatch(false) with empty undo stack");
  2750   /*******************************************************************
  2752    * Make sure that an empty batch is not added to the undo stack
  2753    * when it is closed.
  2755    *******************************************************************/
  2757   result = mgr->GetNumberOfUndoItems(&numitems);
  2759   if (NS_FAILED(result)) {
  2760     fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  2761          result);
  2762     return result;
  2765   if (numitems != 0) {
  2766     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  2767          numitems, result);
  2768     return NS_ERROR_FAILURE;
  2771   result = mgr->BeginBatch(nullptr);
  2773   if (NS_FAILED(result)) {
  2774     fail("BeginBatch(nullptr) failed. (%d)\n", result);
  2775     return result;
  2778   result = mgr->GetNumberOfUndoItems(&numitems);
  2780   if (NS_FAILED(result)) {
  2781     fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  2782          result);
  2783     return result;
  2786   if (numitems != 0) {
  2787     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  2788          numitems, result);
  2789     return NS_ERROR_FAILURE;
  2792   result = mgr->EndBatch(false);
  2794   if (NS_FAILED(result)) {
  2795     fail("EndBatch(false) failed. (%d)\n", result);
  2796     return result;
  2799   result = mgr->GetNumberOfUndoItems(&numitems);
  2801   if (NS_FAILED(result)) {
  2802     fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  2803          result);
  2804     return result;
  2807   if (numitems != 0) {
  2808     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  2809          numitems, result);
  2810     return NS_ERROR_FAILURE;
  2813   passed("Test empty batch");
  2815   int32_t i;
  2816   TestTransaction *tximpl;
  2817   nsITransaction *tx;
  2819   /*******************************************************************
  2821    * Execute 20 transactions. Afterwards, we should have 1
  2822    * transaction on the undo stack:
  2824    *******************************************************************/
  2826   result = mgr->BeginBatch(nullptr);
  2828   if (NS_FAILED(result)) {
  2829     fail("BeginBatch(nullptr) failed. (%d)\n", result);
  2830     return result;
  2833   for (i = 1; i <= 20; i++) {
  2834     tximpl = factory->create(mgr, NONE_FLAG);
  2836     if (!tximpl) {
  2837       fail("Failed to allocate transaction %d.\n", i);
  2838       return NS_ERROR_OUT_OF_MEMORY;
  2841     tx = 0;
  2842     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  2843     if (NS_FAILED(result)) {
  2844       fail("QueryInterface() failed for transaction %d. (%d)\n",
  2845            i, result);
  2846       return result;
  2849     result = mgr->DoTransaction(tx);
  2850     if (NS_FAILED(result)) {
  2851       fail("Failed to execute transaction %d. (%d)\n", i, result);
  2852       return result;
  2855     tx->Release();
  2858   result = mgr->GetNumberOfUndoItems(&numitems);
  2860   if (NS_FAILED(result)) {
  2861     fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  2862          result);
  2863     return result;
  2866   if (numitems != 0) {
  2867     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  2868          numitems, result);
  2869     return NS_ERROR_FAILURE;
  2872   result = mgr->EndBatch(false);
  2874   if (NS_FAILED(result)) {
  2875     fail("EndBatch(false) failed. (%d)\n", result);
  2876     return result;
  2879   result = mgr->GetNumberOfUndoItems(&numitems);
  2881   if (NS_FAILED(result)) {
  2882     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  2883          result);
  2884     return result;
  2887   if (numitems != 1) {
  2888     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  2889          numitems, result);
  2890     return NS_ERROR_FAILURE;
  2893   passed("Execute 20 batched transactions");
  2895   nsITransaction *u1, *u2;
  2896   nsITransaction *r1, *r2;
  2898   /*******************************************************************
  2900    * Execute 20 transient transactions. Afterwards, we should still
  2901    * have the same transaction on the undo stack:
  2903    *******************************************************************/
  2905   u1 = u2 = r1 = r2 = 0;
  2907   result = mgr->PeekUndoStack(&u1);
  2909   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  2911   if (NS_FAILED(result)) {
  2912     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  2913     return result;
  2916   result = mgr->PeekRedoStack(&r1);
  2918   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  2920   if (NS_FAILED(result)) {
  2921     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  2922     return result;
  2925   result = mgr->BeginBatch(nullptr);
  2927   if (NS_FAILED(result)) {
  2928     fail("BeginBatch(nullptr) failed. (%d)\n", result);
  2929     return result;
  2932   for (i = 1; i <= 20; i++) {
  2933     tximpl = factory->create(mgr, TRANSIENT_FLAG);
  2935     if (!tximpl) {
  2936       fail("Failed to allocate transaction %d.\n", i);
  2937       return NS_ERROR_OUT_OF_MEMORY;
  2940     tx = 0;
  2941     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  2942     if (NS_FAILED(result)) {
  2943       fail("QueryInterface() failed for transaction %d. (%d)\n",
  2944            i, result);
  2945       return result;
  2948     result = mgr->DoTransaction(tx);
  2949     if (NS_FAILED(result)) {
  2950       fail("Failed to execute transaction %d. (%d)\n", i, result);
  2951       return result;
  2954     tx->Release();
  2957   result = mgr->EndBatch(false);
  2959   if (NS_FAILED(result)) {
  2960     fail("EndBatch(false) failed. (%d)\n", result);
  2961     return result;
  2964   result = mgr->PeekUndoStack(&u2);
  2966   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  2968   if (NS_FAILED(result)) {
  2969     fail("Second PeekUndoStack() failed. (%d)\n", result);
  2970     return result;
  2973   if (u1 != u2) {
  2974     fail("Top of undo stack changed. (%d)\n", result);
  2975     return NS_ERROR_FAILURE;
  2978   result = mgr->PeekRedoStack(&r2);
  2980   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  2982   if (NS_FAILED(result)) {
  2983     fail("Second PeekRedoStack() failed. (%d)\n", result);
  2984     return result;
  2987   if (r1 != r2) {
  2988     fail("Top of redo stack changed. (%d)\n", result);
  2989     return NS_ERROR_FAILURE;
  2992   result = mgr->GetNumberOfUndoItems(&numitems);
  2994   if (NS_FAILED(result)) {
  2995     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  2996          result);
  2997     return result;
  3000   if (numitems != 1) {
  3001     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  3002          numitems, result);
  3003     return NS_ERROR_FAILURE;
  3006   result = mgr->GetNumberOfRedoItems(&numitems);
  3008   if (NS_FAILED(result)) {
  3009     fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  3010          result);
  3011     return result;
  3014   if (numitems != 0) {
  3015     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  3016          numitems, result);
  3017     return NS_ERROR_FAILURE;
  3020   passed("Execute 20 batched transient transactions");
  3022   /*******************************************************************
  3024    * Test nested batching. Afterwards, we should have 2 transactions
  3025    * on the undo stack:
  3027    *******************************************************************/
  3029   result = mgr->BeginBatch(nullptr);
  3031   if (NS_FAILED(result)) {
  3032     fail("BeginBatch(nullptr) failed. (%d)\n", result);
  3033     return result;
  3036   tximpl = factory->create(mgr, NONE_FLAG);
  3038   if (!tximpl) {
  3039     fail("Failed to allocate transaction.\n");
  3040     return NS_ERROR_OUT_OF_MEMORY;
  3043   tx = 0;
  3044   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  3045   if (NS_FAILED(result)) {
  3046     fail("QueryInterface() failed for transaction. (%d)\n", result);
  3047     return result;
  3050   result = mgr->DoTransaction(tx);
  3051   if (NS_FAILED(result)) {
  3052     fail("Failed to execute transaction. (%d)\n", result);
  3053     return result;
  3056   tx->Release();
  3058   result = mgr->GetNumberOfUndoItems(&numitems);
  3060   if (NS_FAILED(result)) {
  3061     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  3062          result);
  3063     return result;
  3066   if (numitems != 1) {
  3067     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  3068          numitems, result);
  3069     return NS_ERROR_FAILURE;
  3072   result = mgr->BeginBatch(nullptr);
  3074   if (NS_FAILED(result)) {
  3075     fail("BeginBatch(nullptr) failed. (%d)\n", result);
  3076     return result;
  3079   tximpl = factory->create(mgr, NONE_FLAG);
  3081   if (!tximpl) {
  3082     fail("Failed to allocate transaction.\n");
  3083     return NS_ERROR_OUT_OF_MEMORY;
  3086   tx = 0;
  3087   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  3088   if (NS_FAILED(result)) {
  3089     fail("QueryInterface() failed for transaction. (%d)\n", result);
  3090     return result;
  3093   result = mgr->DoTransaction(tx);
  3094   if (NS_FAILED(result)) {
  3095     fail("Failed to execute transaction. (%d)\n", result);
  3096     return result;
  3099   tx->Release();
  3101   result = mgr->GetNumberOfUndoItems(&numitems);
  3103   if (NS_FAILED(result)) {
  3104     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  3105          result);
  3106     return result;
  3109   if (numitems != 1) {
  3110     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  3111          numitems, result);
  3112     return NS_ERROR_FAILURE;
  3115   result = mgr->BeginBatch(nullptr);
  3117   if (NS_FAILED(result)) {
  3118     fail("BeginBatch(nullptr) failed. (%d)\n", result);
  3119     return result;
  3122   tximpl = factory->create(mgr, NONE_FLAG);
  3124   if (!tximpl) {
  3125     fail("Failed to allocate transaction.\n");
  3126     return NS_ERROR_OUT_OF_MEMORY;
  3129   tx = 0;
  3130   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  3131   if (NS_FAILED(result)) {
  3132     fail("QueryInterface() failed for transaction. (%d)\n", result);
  3133     return result;
  3136   result = mgr->DoTransaction(tx);
  3137   if (NS_FAILED(result)) {
  3138     fail("Failed to execute transaction. (%d)\n", result);
  3139     return result;
  3142   tx->Release();
  3144   result = mgr->GetNumberOfUndoItems(&numitems);
  3146   if (NS_FAILED(result)) {
  3147     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  3148          result);
  3149     return result;
  3152   if (numitems != 1) {
  3153     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  3154          numitems, result);
  3155     return NS_ERROR_FAILURE;
  3158   result = mgr->EndBatch(false);
  3160   if (NS_FAILED(result)) {
  3161     fail("EndBatch(false) failed. (%d)\n", result);
  3162     return result;
  3165   result = mgr->EndBatch(false);
  3167   if (NS_FAILED(result)) {
  3168     fail("EndBatch(false) failed. (%d)\n", result);
  3169     return result;
  3172   result = mgr->EndBatch(false);
  3174   if (NS_FAILED(result)) {
  3175     fail("EndBatch(false) failed. (%d)\n", result);
  3176     return result;
  3179   result = mgr->GetNumberOfUndoItems(&numitems);
  3181   if (NS_FAILED(result)) {
  3182     fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
  3183          result);
  3184     return result;
  3187   if (numitems != 2) {
  3188     fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
  3189          numitems, result);
  3190     return NS_ERROR_FAILURE;
  3193   passed("Test nested batched transactions");
  3195   /*******************************************************************
  3197    * Undo 2 batch transactions. Afterwards, we should have 0
  3198    * transactions on the undo stack and 2 on the redo stack.
  3200    *******************************************************************/
  3202   for (i = 1; i <= 2; ++i) {
  3203     result = mgr->UndoTransaction();
  3204     if (NS_FAILED(result)) {
  3205       fail("Failed to undo transaction %d. (%d)\n", i, result);
  3206       return result;
  3210   result = mgr->GetNumberOfUndoItems(&numitems);
  3212   if (NS_FAILED(result)) {
  3213     fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  3214          result);
  3215     return result;
  3218   if (numitems != 0) {
  3219     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  3220          numitems, result);
  3221     return NS_ERROR_FAILURE;
  3224   result = mgr->GetNumberOfRedoItems(&numitems);
  3226   if (NS_FAILED(result)) {
  3227     fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
  3228          result);
  3229     return result;
  3232   if (numitems != 2) {
  3233     fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
  3234          numitems, result);
  3235     return NS_ERROR_FAILURE;
  3238   passed("Undo 2 batch transactions");
  3240   /*******************************************************************
  3242    * Redo 2 batch transactions. Afterwards, we should have 2
  3243    * transactions on the undo stack and 0 on the redo stack.
  3245    *******************************************************************/
  3247   for (i = 1; i <= 2; ++i) {
  3248     result = mgr->RedoTransaction();
  3249     if (NS_FAILED(result)) {
  3250       fail("Failed to undo transaction %d. (%d)\n", i, result);
  3251       return result;
  3255   result = mgr->GetNumberOfUndoItems(&numitems);
  3257   if (NS_FAILED(result)) {
  3258     fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
  3259          result);
  3260     return result;
  3263   if (numitems != 2) {
  3264     fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
  3265          numitems, result);
  3266     return NS_ERROR_FAILURE;
  3269   result = mgr->GetNumberOfRedoItems(&numitems);
  3271   if (NS_FAILED(result)) {
  3272     fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  3273          result);
  3274     return result;
  3277   if (numitems != 0) {
  3278     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  3279          numitems, result);
  3280     return NS_ERROR_FAILURE;
  3283   passed("Redo 2 batch transactions");
  3285   /*******************************************************************
  3287    * Call undo. Afterwards, we should have 1 transaction
  3288    * on the undo stack, and 1 on the redo stack:
  3290    *******************************************************************/
  3292   result = mgr->UndoTransaction();
  3294   if (NS_FAILED(result)) {
  3295     fail("Failed to undo transaction. (%d)\n", result);
  3296     return result;
  3299   result = mgr->GetNumberOfUndoItems(&numitems);
  3301   if (NS_FAILED(result)) {
  3302     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  3303          result);
  3304     return result;
  3307   if (numitems != 1) {
  3308     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  3309          numitems, result);
  3310     return NS_ERROR_FAILURE;
  3313   result = mgr->GetNumberOfRedoItems(&numitems);
  3315   if (NS_FAILED(result)) {
  3316     fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
  3317          result);
  3318     return result;
  3321   if (numitems != 1) {
  3322     fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  3323          numitems, result);
  3324     return NS_ERROR_FAILURE;
  3327   passed("Undo a batched transaction that was redone");
  3329   /*******************************************************************
  3331    * Make sure an unbalanced call to EndBatch(false) throws an error and
  3332    * doesn't affect the undo and redo stacks!
  3334    *******************************************************************/
  3336   result = mgr->EndBatch(false);
  3338   if (result != NS_ERROR_FAILURE) {
  3339     fail("EndBatch(false) returned unexpected status. (%d)\n", result);
  3340     return result;
  3343   result = mgr->GetNumberOfUndoItems(&numitems);
  3345   if (NS_FAILED(result)) {
  3346     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  3347          result);
  3348     return result;
  3351   if (numitems != 1) {
  3352     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  3353          numitems, result);
  3354     return NS_ERROR_FAILURE;
  3357   result = mgr->GetNumberOfRedoItems(&numitems);
  3359   if (NS_FAILED(result)) {
  3360     fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
  3361          result);
  3362     return result;
  3365   if (numitems != 1) {
  3366     fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  3367          numitems, result);
  3368     return NS_ERROR_FAILURE;
  3371   passed("Test effect of unbalanced EndBatch(false) on undo and redo stacks");
  3373   /*******************************************************************
  3375    * Make sure that an empty batch is not added to the undo stack
  3376    * when it is closed, and that it does not affect the undo and redo
  3377    * stacks.
  3379    *******************************************************************/
  3381   result = mgr->BeginBatch(nullptr);
  3383   if (NS_FAILED(result)) {
  3384     fail("BeginBatch(nullptr) failed. (%d)\n", result);
  3385     return result;
  3388   result = mgr->GetNumberOfUndoItems(&numitems);
  3390   if (NS_FAILED(result)) {
  3391     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  3392          result);
  3393     return result;
  3396   if (numitems != 1) {
  3397     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  3398          numitems, result);
  3399     return NS_ERROR_FAILURE;
  3402   result = mgr->GetNumberOfRedoItems(&numitems);
  3404   if (NS_FAILED(result)) {
  3405     fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
  3406          result);
  3407     return result;
  3410   if (numitems != 1) {
  3411     fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  3412          numitems, result);
  3413     return NS_ERROR_FAILURE;
  3416   result = mgr->EndBatch(false);
  3418   if (NS_FAILED(result)) {
  3419     fail("EndBatch(false) failed. (%d)\n", result);
  3420     return result;
  3423   result = mgr->GetNumberOfUndoItems(&numitems);
  3425   if (NS_FAILED(result)) {
  3426     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  3427          result);
  3428     return result;
  3431   if (numitems != 1) {
  3432     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  3433          numitems, result);
  3434     return NS_ERROR_FAILURE;
  3437   result = mgr->GetNumberOfRedoItems(&numitems);
  3439   if (NS_FAILED(result)) {
  3440     fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
  3441          result);
  3442     return result;
  3445   if (numitems != 1) {
  3446     fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  3447          numitems, result);
  3448     return NS_ERROR_FAILURE;
  3451   passed("Test effect of empty batch on undo and redo stacks");
  3453   /*******************************************************************
  3455    * Execute a new transaction. The redo stack should get pruned!
  3457    *******************************************************************/
  3459   result = mgr->BeginBatch(nullptr);
  3461   if (NS_FAILED(result)) {
  3462     fail("BeginBatch(nullptr) failed. (%d)\n", result);
  3463     return result;
  3466   for (i = 1; i <= 20; i++) {
  3467     tximpl = factory->create(mgr, NONE_FLAG);
  3469     if (!tximpl) {
  3470       fail("Failed to allocate transaction %d.\n", i);
  3471       return NS_ERROR_OUT_OF_MEMORY;
  3474     tx = 0;
  3475     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  3476     if (NS_FAILED(result)) {
  3477       fail("QueryInterface() failed for transaction %d. (%d)\n",
  3478            i, result);
  3479       return result;
  3482     result = mgr->DoTransaction(tx);
  3483     if (NS_FAILED(result)) {
  3484       fail("Failed to execute transaction %d. (%d)\n", i, result);
  3485       return result;
  3488     tx->Release();
  3491   result = mgr->GetNumberOfUndoItems(&numitems);
  3493   if (NS_FAILED(result)) {
  3494     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  3495          result);
  3496     return result;
  3499   if (numitems != 1) {
  3500     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  3501          numitems, result);
  3502     return NS_ERROR_FAILURE;
  3505   result = mgr->GetNumberOfRedoItems(&numitems);
  3507   if (NS_FAILED(result)) {
  3508     fail("GetNumberOfRedoItems() on redo stack with 1 item failed. (%d)\n",
  3509          result);
  3510     return result;
  3513   if (numitems != 1) {
  3514     fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  3515          numitems, result);
  3516     return NS_ERROR_FAILURE;
  3519   result = mgr->EndBatch(false);
  3521   if (NS_FAILED(result)) {
  3522     fail("EndBatch(false) failed. (%d)\n", result);
  3523     return result;
  3526   result = mgr->GetNumberOfUndoItems(&numitems);
  3528   if (NS_FAILED(result)) {
  3529     fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
  3530          result);
  3531     return result;
  3534   if (numitems != 2) {
  3535     fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
  3536          numitems, result);
  3537     return NS_ERROR_FAILURE;
  3540   result = mgr->GetNumberOfRedoItems(&numitems);
  3542   if (NS_FAILED(result)) {
  3543     fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  3544          result);
  3545     return result;
  3548   if (numitems != 0) {
  3549     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  3550          numitems, result);
  3551     return NS_ERROR_FAILURE;
  3554   passed("Check if new batched transactions prune the redo stack");
  3556   /*******************************************************************
  3558    * Call undo.
  3560    *******************************************************************/
  3562   // Move a transaction over to the redo stack, so that we have one
  3563   // transaction on the undo stack, and one on the redo stack!
  3565   result = mgr->UndoTransaction();
  3567   if (NS_FAILED(result)) {
  3568     fail("Failed to undo transaction. (%d)\n", result);
  3569     return result;
  3572   result = mgr->GetNumberOfUndoItems(&numitems);
  3574   if (NS_FAILED(result)) {
  3575     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  3576          result);
  3577     return result;
  3580   if (numitems != 1) {
  3581     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  3582          numitems, result);
  3583     return NS_ERROR_FAILURE;
  3586   result = mgr->GetNumberOfRedoItems(&numitems);
  3588   if (NS_FAILED(result)) {
  3589     fail("GetNumberOfRedoItems() on redo stack with 1 item failed. (%d)\n",
  3590          result);
  3591     return result;
  3594   if (numitems != 1) {
  3595     fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  3596          numitems, result);
  3597     return NS_ERROR_FAILURE;
  3600   passed("Call undo");
  3602   /*******************************************************************
  3604    * Test transaction DoTransaction() error:
  3606    *******************************************************************/
  3608   tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
  3610   if (!tximpl) {
  3611     fail("Failed to allocate transaction.\n");
  3612     return NS_ERROR_OUT_OF_MEMORY;
  3615   tx     = 0;
  3617   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  3619   if (NS_FAILED(result)) {
  3620     fail("QueryInterface() failed for transaction. (%d)\n", result);
  3621     return result;
  3624   u1 = u2 = r1 = r2 = 0;
  3626   result = mgr->PeekUndoStack(&u1);
  3628   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  3630   if (NS_FAILED(result)) {
  3631     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  3632     return result;
  3635   result = mgr->PeekRedoStack(&r1);
  3637   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  3639   if (NS_FAILED(result)) {
  3640     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  3641     return result;
  3644   result = mgr->BeginBatch(nullptr);
  3646   if (NS_FAILED(result)) {
  3647     fail("BeginBatch(nullptr) failed. (%d)\n", result);
  3648     return result;
  3651   result = mgr->DoTransaction(tx);
  3653   if (result != NS_ERROR_FAILURE) {
  3654     fail("DoTransaction() returned unexpected error. (%d)\n", result);
  3655     return result;
  3658   tx->Release();
  3660   result = mgr->EndBatch(false);
  3662   if (NS_FAILED(result)) {
  3663     fail("EndBatch(false) failed. (%d)\n", result);
  3664     return result;
  3667   result = mgr->PeekUndoStack(&u2);
  3669   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  3671   if (NS_FAILED(result)) {
  3672     fail("Second PeekUndoStack() failed. (%d)\n", result);
  3673     return result;
  3676   if (u1 != u2) {
  3677     fail("Top of undo stack changed. (%d)\n", result);
  3678     return NS_ERROR_FAILURE;
  3681   result = mgr->PeekRedoStack(&r2);
  3683   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  3685   if (NS_FAILED(result)) {
  3686     fail("Second PeekRedoStack() failed. (%d)\n", result);
  3687     return result;
  3690   if (r1 != r2) {
  3691     fail("Top of redo stack changed. (%d)\n", result);
  3692     return NS_ERROR_FAILURE;
  3695   result = mgr->GetNumberOfUndoItems(&numitems);
  3697   if (NS_FAILED(result)) {
  3698     fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
  3699          result);
  3700     return result;
  3703   if (numitems != 1) {
  3704     fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
  3705          numitems, result);
  3706     return NS_ERROR_FAILURE;
  3709   result = mgr->GetNumberOfRedoItems(&numitems);
  3711   if (NS_FAILED(result)) {
  3712     fail("GetNumberOfRedoItems() on redo stack with 1 item failed. (%d)\n",
  3713          result);
  3714     return result;
  3717   if (numitems != 1) {
  3718     fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
  3719          numitems, result);
  3720     return NS_ERROR_FAILURE;
  3723   passed("Test transaction DoTransaction() error");
  3725   /*******************************************************************
  3727    * Test transaction UndoTransaction() error:
  3729    *******************************************************************/
  3731   tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
  3733   if (!tximpl) {
  3734     fail("Failed to allocate transaction.\n");
  3735     return NS_ERROR_OUT_OF_MEMORY;
  3738   tx     = 0;
  3740   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  3742   if (NS_FAILED(result)) {
  3743     fail("QueryInterface() failed for transaction. (%d)\n", result);
  3744     return result;
  3747   result = mgr->BeginBatch(nullptr);
  3749   if (NS_FAILED(result)) {
  3750     fail("BeginBatch(nullptr) failed. (%d)\n", result);
  3751     return result;
  3754   result = mgr->DoTransaction(tx);
  3756   if (NS_FAILED(result)) {
  3757     fail("DoTransaction() returned unexpected error. (%d)\n", result);
  3758     return result;
  3761   tx->Release();
  3763   result = mgr->EndBatch(false);
  3765   if (NS_FAILED(result)) {
  3766     fail("EndBatch(false) failed. (%d)\n", result);
  3767     return result;
  3770   u1 = u2 = r1 = r2 = 0;
  3772   result = mgr->PeekUndoStack(&u1);
  3774   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  3776   if (NS_FAILED(result)) {
  3777     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  3778     return result;
  3781   result = mgr->PeekRedoStack(&r1);
  3783   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  3785   if (NS_FAILED(result)) {
  3786     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  3787     return result;
  3790   result = mgr->UndoTransaction();
  3792   if (result != NS_ERROR_FAILURE) {
  3793     fail("UndoTransaction() returned unexpected error. (%d)\n", result);
  3794     return result;
  3797   result = mgr->PeekUndoStack(&u2);
  3799   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  3801   if (NS_FAILED(result)) {
  3802     fail("Second PeekUndoStack() failed. (%d)\n", result);
  3803     return result;
  3806   if (u1 != u2) {
  3807     fail("Top of undo stack changed. (%d)\n", result);
  3808     return NS_ERROR_FAILURE;
  3811   result = mgr->PeekRedoStack(&r2);
  3813   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  3815   if (NS_FAILED(result)) {
  3816     fail("Second PeekRedoStack() failed. (%d)\n", result);
  3817     return result;
  3820   if (r1 != r2) {
  3821     fail("Top of redo stack changed. (%d)\n", result);
  3822     return NS_ERROR_FAILURE;
  3825   result = mgr->GetNumberOfUndoItems(&numitems);
  3827   if (NS_FAILED(result)) {
  3828     fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
  3829          result);
  3830     return result;
  3833   if (numitems != 2) {
  3834     fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
  3835          numitems, result);
  3836     return NS_ERROR_FAILURE;
  3839   result = mgr->GetNumberOfRedoItems(&numitems);
  3841   if (NS_FAILED(result)) {
  3842     fail("GetNumberOfRedoItems() on empty redo stack. (%d)\n",
  3843          result);
  3844     return result;
  3847   if (numitems != 0) {
  3848     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  3849          numitems, result);
  3850     return NS_ERROR_FAILURE;
  3853   passed("Test transaction UndoTransaction() error");
  3855   /*******************************************************************
  3857    * Test transaction RedoTransaction() error:
  3859    *******************************************************************/
  3861   tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
  3863   if (!tximpl) {
  3864     fail("Failed to allocate transaction.\n");
  3865     return NS_ERROR_OUT_OF_MEMORY;
  3868   tx     = 0;
  3870   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  3872   if (NS_FAILED(result)) {
  3873     fail("QueryInterface() failed for RedoErrorTransaction. (%d)\n",
  3874          result);
  3875     return result;
  3878   result = mgr->BeginBatch(nullptr);
  3880   if (NS_FAILED(result)) {
  3881     fail("BeginBatch(nullptr) failed. (%d)\n", result);
  3882     return result;
  3885   result = mgr->DoTransaction(tx);
  3887   if (NS_FAILED(result)) {
  3888     fail("DoTransaction() returned unexpected error. (%d)\n", result);
  3889     return result;
  3892   tx->Release();
  3894   result = mgr->EndBatch(false);
  3896   if (NS_FAILED(result)) {
  3897     fail("EndBatch(false) failed. (%d)\n", result);
  3898     return result;
  3901   //
  3902   // Execute a normal transaction to be used in a later test:
  3903   //
  3905   tximpl = factory->create(mgr, NONE_FLAG);
  3907   if (!tximpl) {
  3908     fail("Failed to allocate transaction.\n");
  3909     return NS_ERROR_OUT_OF_MEMORY;
  3912   tx     = 0;
  3914   result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  3916   if (NS_FAILED(result)) {
  3917     fail("QueryInterface() failed for transaction. (%d)\n", result);
  3918     return result;
  3921   result = mgr->DoTransaction(tx);
  3923   if (NS_FAILED(result)) {
  3924     fail("DoTransaction() returned unexpected error. (%d)\n", result);
  3925     return result;
  3928   tx->Release();
  3930   //
  3931   // Undo the 2 transactions just executed.
  3932   //
  3934   for (i = 1; i <= 2; ++i) {
  3935     result = mgr->UndoTransaction();
  3936     if (NS_FAILED(result)) {
  3937       fail("Failed to undo transaction %d. (%d)\n", i, result);
  3938       return result;
  3942   //
  3943   // The RedoErrorTransaction should now be at the top of the redo stack!
  3944   //
  3946   u1 = u2 = r1 = r2 = 0;
  3948   result = mgr->PeekUndoStack(&u1);
  3950   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
  3952   if (NS_FAILED(result)) {
  3953     fail("Initial PeekUndoStack() failed. (%d)\n", result);
  3954     return result;
  3957   result = mgr->PeekRedoStack(&r1);
  3959   TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
  3961   if (NS_FAILED(result)) {
  3962     fail("Initial PeekRedoStack() failed. (%d)\n", result);
  3963     return result;
  3966   result = mgr->RedoTransaction();
  3968   if (result != NS_ERROR_FAILURE) {
  3969     fail("RedoTransaction() returned unexpected error. (%d)\n", result);
  3970     return result;
  3973   result = mgr->PeekUndoStack(&u2);
  3975   TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
  3977   if (NS_FAILED(result)) {
  3978     fail("Second PeekUndoStack() failed. (%d)\n", result);
  3979     return result;
  3982   if (u1 != u2) {
  3983     fail("Top of undo stack changed. (%d)\n", result);
  3984     return NS_ERROR_FAILURE;
  3987   result = mgr->PeekRedoStack(&r2);
  3989   TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
  3991   if (NS_FAILED(result)) {
  3992     fail("Second PeekRedoStack() failed. (%d)\n", result);
  3993     return result;
  3996   if (r1 != r2) {
  3997     fail("Top of redo stack changed. (%d)\n", result);
  3998     return NS_ERROR_FAILURE;
  4001   result = mgr->GetNumberOfUndoItems(&numitems);
  4003   if (NS_FAILED(result)) {
  4004     fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
  4005          result);
  4006     return result;
  4009   if (numitems != 2) {
  4010     fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
  4011          numitems, result);
  4012     return NS_ERROR_FAILURE;
  4015   result = mgr->GetNumberOfRedoItems(&numitems);
  4017   if (NS_FAILED(result)) {
  4018     fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
  4019          result);
  4020     return result;
  4023   if (numitems != 2) {
  4024     fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
  4025          numitems, result);
  4026     return NS_ERROR_FAILURE;
  4029   passed("Test transaction RedoTransaction() error");
  4031   /*******************************************************************
  4033    * Make sure that setting the transaction manager's max transaction
  4034    * count to zero, clears both the undo and redo stacks, and executes
  4035    * all new commands without pushing them on the undo stack!
  4037    *******************************************************************/
  4039   result = mgr->SetMaxTransactionCount(0);
  4041   if (NS_FAILED(result)) {
  4042     fail("SetMaxTransactionCount(0) failed. (%d)\n", result);
  4043     return result;
  4046   result = mgr->GetNumberOfUndoItems(&numitems);
  4048   if (NS_FAILED(result)) {
  4049     fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  4050          result);
  4051     return result;
  4054   if (numitems != 0) {
  4055     fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  4056          numitems, result);
  4057     return NS_ERROR_FAILURE;
  4060   result = mgr->GetNumberOfRedoItems(&numitems);
  4062   if (NS_FAILED(result)) {
  4063     fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  4064          result);
  4065     return result;
  4068   if (numitems != 0) {
  4069     fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  4070          numitems, result);
  4071     return NS_ERROR_FAILURE;
  4074   for (i = 1; i <= 20; i++) {
  4075     tximpl = factory->create(mgr, NONE_FLAG);
  4077     if (!tximpl) {
  4078       fail("Failed to allocate transaction %d.\n", i);
  4079       return NS_ERROR_OUT_OF_MEMORY;
  4082     tx = 0;
  4083     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  4084     if (NS_FAILED(result)) {
  4085       fail("QueryInterface() failed for transaction %d. (%d)\n",
  4086            i, result);
  4087       return result;
  4090     result = mgr->BeginBatch(nullptr);
  4092     if (NS_FAILED(result)) {
  4093       fail("BeginBatch(nullptr) failed. (%d)\n", result);
  4094       return result;
  4097     result = mgr->DoTransaction(tx);
  4098     if (NS_FAILED(result)) {
  4099       fail("Failed to execute transaction %d. (%d)\n", i, result);
  4100       return result;
  4103     tx->Release();
  4105     result = mgr->EndBatch(false);
  4107     if (NS_FAILED(result)) {
  4108       fail("EndBatch(false) failed. (%d)\n", result);
  4109       return result;
  4112     result = mgr->GetNumberOfUndoItems(&numitems);
  4114     if (NS_FAILED(result)) {
  4115       fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
  4116            result);
  4117       return result;
  4120     if (numitems != 0) {
  4121       fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
  4122            numitems, result);
  4123       return NS_ERROR_FAILURE;
  4126     result = mgr->GetNumberOfRedoItems(&numitems);
  4128     if (NS_FAILED(result)) {
  4129       fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  4130            result);
  4131       return result;
  4134     if (numitems != 0) {
  4135       fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  4136            numitems, result);
  4137       return NS_ERROR_FAILURE;
  4141   passed("Test max transaction count of zero");
  4143   /*******************************************************************
  4145    * Release the transaction manager. Any transactions on the undo
  4146    * and redo stack should automatically be released:
  4148    *******************************************************************/
  4150   result = mgr->SetMaxTransactionCount(-1);
  4152   if (NS_FAILED(result)) {
  4153     fail("SetMaxTransactionCount(0) failed. (%d)\n", result);
  4154     return result;
  4157   // Push 20 transactions on the undo stack:
  4159   for (i = 1; i <= 20; i++) {
  4160     tximpl = factory->create(mgr, NONE_FLAG);
  4162     if (!tximpl) {
  4163       fail("Failed to allocate transaction %d.\n", i);
  4164       return NS_ERROR_OUT_OF_MEMORY;
  4167     tx = 0;
  4168     result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  4169     if (NS_FAILED(result)) {
  4170       fail("QueryInterface() failed for transaction %d. (%d)\n",
  4171            i, result);
  4172       return result;
  4175     result = mgr->BeginBatch(nullptr);
  4177     if (NS_FAILED(result)) {
  4178       fail("BeginBatch(nullptr) failed. (%d)\n", result);
  4179       return result;
  4182     result = mgr->DoTransaction(tx);
  4183     if (NS_FAILED(result)) {
  4184       fail("Failed to execute transaction %d. (%d)\n", i, result);
  4185       return result;
  4188     tx->Release();
  4190     result = mgr->EndBatch(false);
  4192     if (NS_FAILED(result)) {
  4193       fail("EndBatch(false) failed. (%d)\n", result);
  4194       return result;
  4197     result = mgr->GetNumberOfUndoItems(&numitems);
  4199     if (NS_FAILED(result)) {
  4200       fail("GetNumberOfUndoItems() on undo stack with %d items failed. (%d)\n",
  4201            i, result);
  4202       return result;
  4205     if (numitems != i) {
  4206       fail("GetNumberOfUndoItems() expected %d got %d. (%d)\n",
  4207            i, numitems, result);
  4208       return NS_ERROR_FAILURE;
  4211     result = mgr->GetNumberOfRedoItems(&numitems);
  4213     if (NS_FAILED(result)) {
  4214       fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
  4215            result);
  4216       return result;
  4219     if (numitems != 0) {
  4220       fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
  4221            numitems, result);
  4222       return NS_ERROR_FAILURE;
  4226   for (i = 1; i <= 10; i++) {
  4228     result = mgr->UndoTransaction();
  4229     if (NS_FAILED(result)) {
  4230       fail("Failed to undo transaction %d. (%d)\n", i, result);
  4231       return result;
  4234   result = mgr->GetNumberOfUndoItems(&numitems);
  4236   if (NS_FAILED(result)) {
  4237     fail("GetNumberOfUndoItems() on empty undo stack with 10 items failed. (%d)\n",
  4238          result);
  4239     return result;
  4242   if (numitems != 10) {
  4243     fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
  4244          numitems, result);
  4245     return NS_ERROR_FAILURE;
  4248   result = mgr->GetNumberOfRedoItems(&numitems);
  4250   if (NS_FAILED(result)) {
  4251     fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
  4252          result);
  4253     return result;
  4256   if (numitems != 10) {
  4257     fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
  4258          numitems, result);
  4259     return NS_ERROR_FAILURE;
  4262   result = mgr->Clear();
  4263   if (NS_FAILED(result)) {
  4264     fail("Clear() failed. (%d)\n", result);
  4265     return result;
  4268   passed("Release the transaction manager");
  4270   /*******************************************************************
  4272    * Make sure number of transactions created matches number of
  4273    * transactions destroyed!
  4275    *******************************************************************/
  4277   /* Disabled because the current cycle collector doesn't delete
  4278      cycle collectable objects synchronously.
  4279   if (sConstructorCount != sDestructorCount) {
  4280     fail("Transaction constructor count (%d) != destructor count (%d).\n",
  4281          sConstructorCount, sDestructorCount);
  4282     return NS_ERROR_FAILURE;
  4283   }*/
  4285   passed("Number of transactions created and destroyed match");
  4286   passed("%d transactions processed during quick batch test",
  4287          sConstructorCount);
  4289   return NS_OK;
  4292 nsresult
  4293 simple_batch_test()
  4295   /*******************************************************************
  4297    * Initialize globals for test.
  4299    *******************************************************************/
  4300   reset_globals();
  4301   sDestructorOrderArr = sSimpleBatchTestDestructorOrderArr;
  4302   sDoOrderArr         = sSimpleBatchTestDoOrderArr;
  4303   sUndoOrderArr       = sSimpleBatchTestUndoOrderArr;
  4304   sRedoOrderArr       = sSimpleBatchTestRedoOrderArr;
  4306   /*******************************************************************
  4308    * Run the quick batch test.
  4310    *******************************************************************/
  4312   printf("\n-----------------------------------------------------\n");
  4313   printf("- Begin Batch Transaction Test:\n");
  4314   printf("-----------------------------------------------------\n");
  4316   SimpleTransactionFactory factory;
  4318   return quick_batch_test(&factory);
  4321 nsresult
  4322 aggregation_batch_test()
  4324   /*******************************************************************
  4326    * Initialize globals for test.
  4328    *******************************************************************/
  4330   reset_globals();
  4331   sDestructorOrderArr = sAggregateBatchTestDestructorOrderArr;
  4332   sDoOrderArr         = sAggregateBatchTestDoOrderArr;
  4333   sUndoOrderArr       = sAggregateBatchTestUndoOrderArr;
  4334   sRedoOrderArr       = sAggregateBatchTestRedoOrderArr;
  4336   /*******************************************************************
  4338    * Run the quick batch test.
  4340    *******************************************************************/
  4342   printf("\n-----------------------------------------------------\n");
  4343   printf("- Begin Batch Aggregate Transaction Test:\n");
  4344   printf("-----------------------------------------------------\n");
  4346   AggregateTransactionFactory factory(3, 2, BATCH_FLAG);
  4348   return quick_batch_test(&factory);
  4351 /**
  4352  * Create 'iterations * (iterations + 1) / 2' transactions;
  4353  * do/undo/redo/undo them.
  4354  **/
  4355 nsresult
  4356 stress_test(TestTransactionFactory *factory, int32_t iterations)
  4358   printf("Stress test of %i iterations (may take a while) ... ", iterations);
  4359   fflush(stdout);
  4361   nsresult result;
  4363   /*******************************************************************
  4365    * Create a transaction manager:
  4367    *******************************************************************/
  4369   nsCOMPtr<nsITransactionManager> mgr =
  4370     do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
  4371   if (NS_FAILED(result) || !mgr) {
  4372     fail("Failed to create Transaction Manager instance.\n");
  4373     return NS_ERROR_OUT_OF_MEMORY;
  4376   int32_t i, j;
  4377   nsITransaction *tx;
  4379   for (i = 1; i <= iterations; i++) {
  4380     /*******************************************************************
  4382      * Create and execute a bunch of transactions:
  4384      *******************************************************************/
  4386     for (j = 1; j <= i; j++) {
  4387       TestTransaction *tximpl = factory->create(mgr, NONE_FLAG);
  4389       if (!tximpl) {
  4390         fail("Failed to allocate transaction %d-%d.\n", i, j);
  4391         return NS_ERROR_OUT_OF_MEMORY;
  4394       tx = 0;
  4395       result = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
  4396       if (NS_FAILED(result)) {
  4397         fail("QueryInterface() failed for transaction %d-%d. (%d)\n",
  4398              i, j, result);
  4399         return result;
  4402       result = mgr->DoTransaction(tx);
  4403       if (NS_FAILED(result)) {
  4404         fail("Failed to execute transaction %d-%d. (%d)\n",
  4405              i, j, result);
  4406         return result;
  4409       tx->Release();
  4412     /*******************************************************************
  4414      * Undo all the transactions:
  4416      *******************************************************************/
  4418     for (j = 1; j <= i; j++) {
  4419       result = mgr->UndoTransaction();
  4420       if (NS_FAILED(result)) {
  4421         fail("Failed to undo transaction %d-%d. (%d)\n", i, j, result);
  4422         return result;
  4426     /*******************************************************************
  4428      * Redo all the transactions:
  4430      *******************************************************************/
  4432     for (j = 1; j <= i; j++) {
  4433       result = mgr->RedoTransaction();
  4434       if (NS_FAILED(result)) {
  4435         fail("Failed to redo transaction %d-%d. (%d)\n", i, j, result);
  4436         return result;
  4440     /*******************************************************************
  4442      * Undo all the transactions again so that they all end up on
  4443      * the redo stack for pruning the next time we execute a new
  4444      * transaction
  4446      *******************************************************************/
  4448     for (j = 1; j <= i; j++) {
  4449       result = mgr->UndoTransaction();
  4450       if (NS_FAILED(result)) {
  4451         fail("Failed to undo transaction %d-%d. (%d)\n", i, j, result);
  4452         return result;
  4456     // Trivial feedback not to let the user think the test is stuck.
  4457     if (MOZ_UNLIKELY(j % 100 == 0))
  4458       printf("%i ", j);
  4459   } // for, iterations.
  4461   printf("passed\n");
  4463   result = mgr->Clear();
  4464   if (NS_FAILED(result)) {
  4465     fail("Clear() failed. (%d)\n", result);
  4466     return result;
  4469   /* Disabled because the current cycle collector doesn't delete
  4470      cycle collectable objects synchronously.
  4471   if (sConstructorCount != sDestructorCount) {
  4472     fail("Transaction constructor count (%d) != destructor count (%d).\n",
  4473          sConstructorCount, sDestructorCount);
  4474     return NS_ERROR_FAILURE;
  4475   }*/
  4477   passed("%d transactions processed during stress test", sConstructorCount);
  4479   return NS_OK;
  4482 nsresult
  4483 simple_stress_test()
  4485   /*******************************************************************
  4487    * Initialize globals for test.
  4489    *******************************************************************/
  4491   reset_globals();
  4493   /*******************************************************************
  4495    * Do the stress test:
  4497    *******************************************************************/
  4499   printf("\n-----------------------------------------------------\n");
  4500   printf("- Simple Transaction Stress Test:\n");
  4501   printf("-----------------------------------------------------\n");
  4503   SimpleTransactionFactory factory;
  4505   int32_t iterations =
  4506 #ifdef DEBUG
  4507   10
  4508 #else
  4509   //
  4510   // 1500 iterations sends 1,125,750 transactions through the system!!
  4511   //
  4512   1500
  4513 #endif
  4515   return stress_test(&factory, iterations);
  4518 nsresult
  4519 aggregation_stress_test()
  4521   /*******************************************************************
  4523    * Initialize globals for test.
  4525    *******************************************************************/
  4527   reset_globals();
  4529   /*******************************************************************
  4531    * Do the stress test:
  4533    *******************************************************************/
  4535   printf("\n-----------------------------------------------------\n");
  4536   printf("- Aggregate Transaction Stress Test:\n");
  4537   printf("-----------------------------------------------------\n");
  4539   AggregateTransactionFactory factory(3, 4);
  4541   int32_t iterations =
  4542 #ifdef DEBUG
  4543   10
  4544 #else
  4545   //
  4546   // 500 iterations sends 2,630,250 transactions through the system!!
  4547   //
  4548   500
  4549 #endif
  4551   return stress_test(&factory, iterations);
  4554 nsresult
  4555 aggregation_batch_stress_test()
  4557   /*******************************************************************
  4559    * Initialize globals for test.
  4561    *******************************************************************/
  4563   reset_globals();
  4565   /*******************************************************************
  4567    * Do the stress test:
  4569    *******************************************************************/
  4571   printf("\n-----------------------------------------------------\n");
  4572   printf("- Aggregate Batch Transaction Stress Test:\n");
  4573   printf("-----------------------------------------------------\n");
  4575   AggregateTransactionFactory factory(3, 4, BATCH_FLAG);
  4577   int32_t iterations =
  4578 #ifdef DEBUG
  4579   10
  4580 #else
  4581 #if defined(MOZ_ASAN) || defined(MOZ_WIDGET_ANDROID)
  4582   // See Bug 929985: 500 is too many for ASAN and Android, 100 is safe.
  4583   100
  4584 #else
  4585   //
  4586   // 500 iterations sends 2,630,250 transactions through the system!!
  4587   //
  4588   500
  4589 #endif
  4590 #endif
  4592   return stress_test(&factory, iterations);
  4595 int
  4596 main (int argc, char *argv[])
  4598   ScopedXPCOM xpcom("nsITransactionManager");
  4599   if (xpcom.failed())
  4600     return 1;
  4602   nsresult result;
  4604   //
  4605   // quick_test() part:
  4606   //
  4608   result = simple_test();
  4609   NS_ENSURE_SUCCESS(result, 1);
  4611   result = aggregation_test();
  4612   NS_ENSURE_SUCCESS(result, 1);
  4614   //
  4615   // quick_batch_test() part:
  4616   //
  4618   result = simple_batch_test();
  4619   NS_ENSURE_SUCCESS(result, 1);
  4621   result = aggregation_batch_test();
  4622   NS_ENSURE_SUCCESS(result, 1);
  4624   //
  4625   // stress_test() part:
  4626   //
  4628   result = simple_stress_test();
  4629   NS_ENSURE_SUCCESS(result, 1);
  4631   result = aggregation_stress_test();
  4632   NS_ENSURE_SUCCESS(result, 1);
  4634   result = aggregation_batch_stress_test();
  4635   NS_ENSURE_SUCCESS(result, 1);
  4637   return 0;

mercurial