tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestTXMgr.cpp (63779B)


      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/. */
      5 
      6 #include "gtest/gtest.h"
      7 
      8 #include "nsITransactionManager.h"
      9 #include "nsComponentManagerUtils.h"
     10 #include "mozilla/gtest/MozAssertions.h"
     11 #include "mozilla/EditTransactionBase.h"
     12 #include "mozilla/TransactionManager.h"
     13 
     14 using mozilla::EditTransactionBase;
     15 using mozilla::TransactionManager;
     16 
     17 static int32_t sConstructorCount = 0;
     18 static int32_t sDoCount = 0;
     19 static int32_t* sDoOrderArr = 0;
     20 static int32_t sUndoCount = 0;
     21 static int32_t* sUndoOrderArr = 0;
     22 static int32_t sRedoCount = 0;
     23 static int32_t* sRedoOrderArr = 0;
     24 
     25 int32_t sSimpleTestDoOrderArr[] = {
     26    1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,
     27    16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,
     28    31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,
     29    46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,
     30    61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,
     31    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
     32    91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105,
     33    106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
     34    121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131};
     35 
     36 int32_t sSimpleTestUndoOrderArr[] = {41,  40,  39,  38,  62,  39,  38,  37,
     37                                     69,  71,  70,  111, 110, 109, 108, 107,
     38                                     106, 105, 104, 103, 102, 131, 130, 129,
     39                                     128, 127, 126, 125, 124, 123, 122};
     40 
     41 static int32_t sSimpleTestRedoOrderArr[] = {38, 39, 70};
     42 
     43 int32_t sAggregateTestDoOrderArr[] = {
     44    1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,
     45    16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,
     46    31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,
     47    46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,
     48    61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,
     49    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
     50    91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105,
     51    106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
     52    121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
     53    136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
     54    151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
     55    166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
     56    181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
     57    196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
     58    211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,
     59    226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
     60    241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
     61    256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270,
     62    271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
     63    286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300,
     64    301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
     65    316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330,
     66    331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345,
     67    346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360,
     68    361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375,
     69    376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390,
     70    391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405,
     71    406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
     72    421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435,
     73    436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450,
     74    451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465,
     75    466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480,
     76    481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495,
     77    496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510,
     78    511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525,
     79    526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540,
     80    541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555,
     81    556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570,
     82    571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585,
     83    586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600,
     84    601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615,
     85    616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630,
     86    631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645,
     87    646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660,
     88    661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675,
     89    676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690,
     90    691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705,
     91    706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720,
     92    721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735,
     93    736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750,
     94    751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765,
     95    766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780,
     96    781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795,
     97    796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810,
     98    811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825,
     99    826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840,
    100    841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855,
    101    856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870,
    102    871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885,
    103    886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900,
    104    901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913};
    105 
    106 int32_t sAggregateTestUndoOrderArr[] = {
    107    287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273,
    108    272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260, 434, 433,
    109    432, 431, 430, 429, 428, 273, 272, 271, 270, 269, 268, 267, 266, 265, 264,
    110    263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 479, 478, 477, 476,
    111    475, 493, 492, 491, 490, 489, 488, 487, 486, 485, 484, 483, 482, 481, 480,
    112    485, 484, 483, 482, 481, 480, 773, 772, 771, 770, 769, 768, 767, 766, 765,
    113    764, 763, 762, 761, 760, 759, 758, 757, 756, 755, 754, 753, 752, 751, 750,
    114    749, 748, 747, 746, 745, 744, 743, 742, 741, 740, 739, 738, 737, 736, 735,
    115    734, 733, 732, 731, 730, 729, 728, 727, 726, 725, 724, 723, 722, 721, 720,
    116    719, 718, 717, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707, 706, 705,
    117    704, 913, 912, 911, 910, 909, 908, 907, 906, 905, 904, 903, 902, 901, 900,
    118    899, 898, 897, 896, 895, 894, 893, 892, 891, 890, 889, 888, 887, 886, 885,
    119    884, 883, 882, 881, 880, 879, 878, 877, 876, 875, 874, 873, 872, 871, 870,
    120    869, 868, 867, 866, 865, 864, 863, 862, 861, 860, 859, 858, 857, 856, 855,
    121    854, 853, 852, 851, 850, 849, 848, 847, 846, 845, 844};
    122 
    123 int32_t sAggregateTestRedoOrderArr[] = {
    124    260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
    125    273, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486};
    126 
    127 int32_t sSimpleBatchTestDoOrderArr[] = {
    128    1,  2,  3,  4,   5,   6,   7,   8,   9,   10,  11, 12, 13, 14, 15, 16,
    129    17, 18, 19, 20,  21,  22,  23,  24,  25,  26,  27, 28, 29, 30, 31, 32,
    130    33, 34, 35, 36,  37,  38,  39,  40,  41,  42,  43, 44, 45, 46, 47, 48,
    131    49, 50, 51, 52,  53,  54,  55,  56,  57,  58,  59, 60, 61, 62, 63, 64,
    132    65, 66, 67, 68,  69,  70,  71,  72,  73,  74,  75, 76, 77, 78, 79, 80,
    133    81, 82, 83, 84,  85,  86,  87,  88,  89,  90,  91, 92, 93, 94, 95, 96,
    134    97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107};
    135 
    136 int32_t sSimpleBatchTestUndoOrderArr[] = {
    137    43, 42, 41, 20, 19,  18,  17,  16,  15,  14,  13,  12,  11, 10, 9,
    138    8,  7,  6,  5,  4,   3,   2,   1,   43,  42,  41,  63,  62, 61, 60,
    139    59, 58, 57, 56, 55,  54,  53,  52,  51,  50,  49,  48,  47, 46, 45,
    140    44, 65, 67, 66, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98};
    141 
    142 int32_t sSimpleBatchTestRedoOrderArr[] = {1,  2,  3,  4,  5,  6,  7,  8,
    143                                          9,  10, 11, 12, 13, 14, 15, 16,
    144                                          17, 18, 19, 20, 41, 42, 43, 66};
    145 
    146 int32_t sAggregateBatchTestDoOrderArr[] = {
    147    1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,
    148    16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,
    149    31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,
    150    46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,
    151    61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,
    152    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
    153    91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105,
    154    106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
    155    121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
    156    136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
    157    151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
    158    166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
    159    181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
    160    196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
    161    211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,
    162    226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
    163    241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
    164    256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270,
    165    271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
    166    286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300,
    167    301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
    168    316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330,
    169    331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345,
    170    346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360,
    171    361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375,
    172    376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390,
    173    391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405,
    174    406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
    175    421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435,
    176    436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450,
    177    451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465,
    178    466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480,
    179    481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495,
    180    496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510,
    181    511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525,
    182    526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540,
    183    541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555,
    184    556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570,
    185    571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585,
    186    586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600,
    187    601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615,
    188    616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630,
    189    631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645,
    190    646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660,
    191    661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675,
    192    676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690,
    193    691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705,
    194    706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720,
    195    721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735,
    196    736, 737, 738, 739, 740, 741, 742, 743, 744, 745};
    197 
    198 int32_t sAggregateBatchTestUndoOrderArr[] = {
    199    301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287,
    200    286, 285, 284, 283, 282, 281, 140, 139, 138, 137, 136, 135, 134, 133, 132,
    201    131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117,
    202    116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102,
    203    101, 100, 99,  98,  97,  96,  95,  94,  93,  92,  91,  90,  89,  88,  87,
    204    86,  85,  84,  83,  82,  81,  80,  79,  78,  77,  76,  75,  74,  73,  72,
    205    71,  70,  69,  68,  67,  66,  65,  64,  63,  62,  61,  60,  59,  58,  57,
    206    56,  55,  54,  53,  52,  51,  50,  49,  48,  47,  46,  45,  44,  43,  42,
    207    41,  40,  39,  38,  37,  36,  35,  34,  33,  32,  31,  30,  29,  28,  27,
    208    26,  25,  24,  23,  22,  21,  20,  19,  18,  17,  16,  15,  14,  13,  12,
    209    11,  10,  9,   8,   7,   6,   5,   4,   3,   2,   1,   301, 300, 299, 298,
    210    297, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283,
    211    282, 281, 441, 440, 439, 438, 437, 436, 435, 434, 433, 432, 431, 430, 429,
    212    428, 427, 426, 425, 424, 423, 422, 421, 420, 419, 418, 417, 416, 415, 414,
    213    413, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, 400, 399,
    214    398, 397, 396, 395, 394, 393, 392, 391, 390, 389, 388, 387, 386, 385, 384,
    215    383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 370, 369,
    216    368, 367, 366, 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, 354,
    217    353, 352, 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340, 339,
    218    338, 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, 324,
    219    323, 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, 312, 311, 310, 309,
    220    308, 307, 306, 305, 304, 303, 302, 451, 450, 449, 448, 447, 465, 464, 463,
    221    462, 461, 460, 459, 458, 457, 456, 455, 454, 453, 452, 457, 456, 455, 454,
    222    453, 452, 745, 744, 743, 742, 741, 740, 739, 738, 737, 736, 735, 734, 733,
    223    732, 731, 730, 729, 728, 727, 726, 725, 724, 723, 722, 721, 720, 719, 718,
    224    717, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707, 706, 705, 704, 703,
    225    702, 701, 700, 699, 698, 697, 696, 695, 694, 693, 692, 691, 690, 689, 688,
    226    687, 686, 685, 684, 683, 682, 681, 680, 679, 678, 677, 676};
    227 
    228 int32_t sAggregateBatchTestRedoOrderArr[] = {
    229    1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,
    230    16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,
    231    31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,
    232    46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,
    233    61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,
    234    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
    235    91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105,
    236    106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
    237    121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
    238    136, 137, 138, 139, 140, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
    239    291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 448, 449, 450, 451,
    240    452, 453, 454, 455, 456, 457, 458};
    241 
    242 class TestTransaction : public nsITransaction {
    243 protected:
    244  virtual ~TestTransaction() = default;
    245 
    246 public:
    247  TestTransaction() {}
    248 
    249  NS_DECL_ISUPPORTS
    250 
    251  NS_IMETHOD GetAsEditTransactionBase(EditTransactionBase**) final {
    252    return NS_ERROR_NOT_IMPLEMENTED;
    253  }
    254 };
    255 
    256 NS_IMPL_ISUPPORTS(TestTransaction, nsITransaction)
    257 
    258 class SimpleTransaction : public TestTransaction {
    259 protected:
    260 #define NONE_FLAG 0
    261 #define THROWS_DO_ERROR_FLAG 1
    262 #define THROWS_UNDO_ERROR_FLAG 2
    263 #define THROWS_REDO_ERROR_FLAG 4
    264 #define MERGE_FLAG 8
    265 #define TRANSIENT_FLAG 16
    266 #define BATCH_FLAG 32
    267 #define ALL_ERROR_FLAGS \
    268  (THROWS_DO_ERROR_FLAG | THROWS_UNDO_ERROR_FLAG | THROWS_REDO_ERROR_FLAG)
    269 
    270  int32_t mVal;
    271  int32_t mFlags;
    272 
    273 public:
    274  explicit SimpleTransaction(int32_t aFlags = NONE_FLAG)
    275      : mVal(++sConstructorCount), mFlags(aFlags) {}
    276 
    277  ~SimpleTransaction() override = default;
    278 
    279  MOZ_CAN_RUN_SCRIPT NS_IMETHOD DoTransaction() override {
    280    //
    281    // Make sure DoTransaction() is called in the order we expect!
    282    // Notice that we don't check to see if we go past the end of the array.
    283    // This is done on purpose since we want to crash if the order array is out
    284    // of date.
    285    //
    286    if (sDoOrderArr) {
    287      EXPECT_EQ(mVal, sDoOrderArr[sDoCount]);
    288    }
    289 
    290    ++sDoCount;
    291 
    292    return (mFlags & THROWS_DO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
    293  }
    294 
    295  MOZ_CAN_RUN_SCRIPT NS_IMETHOD UndoTransaction() override {
    296    //
    297    // Make sure UndoTransaction() is called in the order we expect!
    298    // Notice that we don't check to see if we go past the end of the array.
    299    // This is done on purpose since we want to crash if the order array is out
    300    // of date.
    301    //
    302    if (sUndoOrderArr) {
    303      EXPECT_EQ(mVal, sUndoOrderArr[sUndoCount]);
    304    }
    305 
    306    ++sUndoCount;
    307 
    308    return (mFlags & THROWS_UNDO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
    309  }
    310 
    311  MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction() override {
    312    //
    313    // Make sure RedoTransaction() is called in the order we expect!
    314    // Notice that we don't check to see if we go past the end of the array.
    315    // This is done on purpose since we want to crash if the order array is out
    316    // of date.
    317    //
    318    if (sRedoOrderArr) {
    319      EXPECT_EQ(mVal, sRedoOrderArr[sRedoCount]);
    320    }
    321 
    322    ++sRedoCount;
    323 
    324    return (mFlags & THROWS_REDO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
    325  }
    326 
    327  NS_IMETHOD GetIsTransient(bool* aIsTransient) override {
    328    if (aIsTransient) {
    329      *aIsTransient = (mFlags & TRANSIENT_FLAG) ? true : false;
    330    }
    331    return NS_OK;
    332  }
    333 
    334  NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override {
    335    if (aDidMerge) {
    336      *aDidMerge = (mFlags & MERGE_FLAG) ? true : false;
    337    }
    338    return NS_OK;
    339  }
    340 };
    341 
    342 class AggregateTransaction : public SimpleTransaction {
    343 private:
    344  AggregateTransaction(nsITransactionManager* aTXMgr, int32_t aLevel,
    345                       int32_t aNumber, int32_t aMaxLevel,
    346                       int32_t aNumChildrenPerNode, int32_t aFlags) {
    347    mLevel = aLevel;
    348    mNumber = aNumber;
    349    mTXMgr = aTXMgr;
    350    mFlags = aFlags & (~ALL_ERROR_FLAGS);
    351    mErrorFlags = aFlags & ALL_ERROR_FLAGS;
    352    mTXMgr = aTXMgr;
    353    mMaxLevel = aMaxLevel;
    354    mNumChildrenPerNode = aNumChildrenPerNode;
    355  }
    356 
    357  nsITransactionManager* mTXMgr;
    358 
    359  int32_t mLevel;
    360  int32_t mNumber;
    361  int32_t mErrorFlags;
    362 
    363  int32_t mMaxLevel;
    364  int32_t mNumChildrenPerNode;
    365 
    366 public:
    367  AggregateTransaction(nsITransactionManager* aTXMgr, int32_t aMaxLevel,
    368                       int32_t aNumChildrenPerNode,
    369                       int32_t aFlags = NONE_FLAG) {
    370    mLevel = 1;
    371    mNumber = 1;
    372    mFlags = aFlags & (~ALL_ERROR_FLAGS);
    373    mErrorFlags = aFlags & ALL_ERROR_FLAGS;
    374    mTXMgr = aTXMgr;
    375    mMaxLevel = aMaxLevel;
    376    mNumChildrenPerNode = aNumChildrenPerNode;
    377  }
    378 
    379  ~AggregateTransaction() override = default;
    380 
    381  MOZ_CAN_RUN_SCRIPT NS_IMETHOD DoTransaction() override {
    382    if (mLevel >= mMaxLevel) {
    383      // Only leaf nodes can throw errors!
    384      mFlags |= mErrorFlags;
    385    }
    386 
    387    nsresult rv = SimpleTransaction::DoTransaction();
    388    if (NS_FAILED(rv)) {
    389      // fail("QueryInterface() failed for transaction level %d. (%d)\n",
    390      //      mLevel, rv);
    391      return rv;
    392    }
    393 
    394    if (mLevel >= mMaxLevel) {
    395      return NS_OK;
    396    }
    397 
    398    if (mFlags & BATCH_FLAG) {
    399      rv = MOZ_KnownLive(mTXMgr)->BeginBatch(nullptr);
    400      if (NS_FAILED(rv)) {
    401        return rv;
    402      }
    403    }
    404 
    405    int32_t cLevel = mLevel + 1;
    406 
    407    for (int i = 1; i <= mNumChildrenPerNode; i++) {
    408      int32_t flags = mErrorFlags & THROWS_DO_ERROR_FLAG;
    409 
    410      if ((mErrorFlags & THROWS_REDO_ERROR_FLAG) && i == mNumChildrenPerNode) {
    411        // Make the rightmost leaf transaction throw the error!
    412        flags = THROWS_REDO_ERROR_FLAG;
    413        mErrorFlags = mErrorFlags & (~THROWS_REDO_ERROR_FLAG);
    414      } else if ((mErrorFlags & THROWS_UNDO_ERROR_FLAG) && i == 1) {
    415        // Make the leftmost leaf transaction throw the error!
    416        flags = THROWS_UNDO_ERROR_FLAG;
    417        mErrorFlags = mErrorFlags & (~THROWS_UNDO_ERROR_FLAG);
    418      }
    419 
    420      flags |= mFlags & BATCH_FLAG;
    421 
    422      RefPtr<AggregateTransaction> tximpl = new AggregateTransaction(
    423          mTXMgr, cLevel, i, mMaxLevel, mNumChildrenPerNode, flags);
    424 
    425      rv = MOZ_KnownLive(mTXMgr)->DoTransaction(tximpl);
    426      if (NS_FAILED(rv)) {
    427        if (mFlags & BATCH_FLAG) {
    428          mTXMgr->EndBatch(false);
    429        }
    430        return rv;
    431      }
    432    }
    433 
    434    if (mFlags & BATCH_FLAG) {
    435      mTXMgr->EndBatch(false);
    436    }
    437    return rv;
    438  }
    439 };
    440 
    441 class TestTransactionFactory {
    442 public:
    443  virtual TestTransaction* create(nsITransactionManager* txmgr,
    444                                  int32_t flags) = 0;
    445 };
    446 
    447 class SimpleTransactionFactory : public TestTransactionFactory {
    448 public:
    449  TestTransaction* create(nsITransactionManager* txmgr,
    450                          int32_t flags) override {
    451    return (TestTransaction*)new SimpleTransaction(flags);
    452  }
    453 };
    454 
    455 class AggregateTransactionFactory : public TestTransactionFactory {
    456 private:
    457  int32_t mMaxLevel;
    458  int32_t mNumChildrenPerNode;
    459  int32_t mFixedFlags;
    460 
    461 public:
    462  AggregateTransactionFactory(int32_t aMaxLevel, int32_t aNumChildrenPerNode,
    463                              int32_t aFixedFlags = NONE_FLAG)
    464      : mMaxLevel(aMaxLevel),
    465        mNumChildrenPerNode(aNumChildrenPerNode),
    466        mFixedFlags(aFixedFlags) {}
    467 
    468  TestTransaction* create(nsITransactionManager* txmgr,
    469                          int32_t flags) override {
    470    return (TestTransaction*)new AggregateTransaction(
    471        txmgr, mMaxLevel, mNumChildrenPerNode, flags | mFixedFlags);
    472  }
    473 };
    474 
    475 void reset_globals() {
    476  sConstructorCount = 0;
    477 
    478  sDoCount = 0;
    479  sDoOrderArr = 0;
    480 
    481  sUndoCount = 0;
    482  sUndoOrderArr = 0;
    483 
    484  sRedoCount = 0;
    485  sRedoOrderArr = 0;
    486 }
    487 
    488 /**
    489 * Test behaviors in non-batch mode.
    490 **/
    491 MOZ_CAN_RUN_SCRIPT_BOUNDARY void quick_test(TestTransactionFactory* factory) {
    492  /*******************************************************************
    493   *
    494   * Create a transaction manager implementation:
    495   *
    496   *******************************************************************/
    497 
    498  nsCOMPtr<nsITransactionManager> mgr = new TransactionManager();
    499 
    500  /*******************************************************************
    501   *
    502   * Call DoTransaction() with a null transaction:
    503   *
    504   *******************************************************************/
    505 
    506  nsresult rv = mgr->DoTransaction(nullptr);
    507  EXPECT_EQ(rv, NS_ERROR_NULL_POINTER);
    508 
    509  /*******************************************************************
    510   *
    511   * Call UndoTransaction() with an empty undo stack:
    512   *
    513   *******************************************************************/
    514 
    515  rv = mgr->UndoTransaction();
    516  EXPECT_NS_SUCCEEDED(rv);
    517 
    518  /*******************************************************************
    519   *
    520   * Call RedoTransaction() with an empty redo stack:
    521   *
    522   *******************************************************************/
    523 
    524  rv = mgr->RedoTransaction();
    525  EXPECT_NS_SUCCEEDED(rv);
    526 
    527  /*******************************************************************
    528   *
    529   * Call SetMaxTransactionCount(-1) with empty undo and redo stacks:
    530   *
    531   *******************************************************************/
    532 
    533  rv = mgr->SetMaxTransactionCount(-1);
    534  EXPECT_NS_SUCCEEDED(rv);
    535 
    536  /*******************************************************************
    537   *
    538   * Call SetMaxTransactionCount(0) with empty undo and redo stacks:
    539   *
    540   *******************************************************************/
    541 
    542  rv = mgr->SetMaxTransactionCount(0);
    543  EXPECT_NS_SUCCEEDED(rv);
    544 
    545  /*******************************************************************
    546   *
    547   * Call SetMaxTransactionCount(10) with empty undo and redo stacks:
    548   *
    549   *******************************************************************/
    550 
    551  rv = mgr->SetMaxTransactionCount(10);
    552  EXPECT_NS_SUCCEEDED(rv);
    553 
    554  /*******************************************************************
    555   *
    556   * Call Clear() with empty undo and redo stacks:
    557   *
    558   *******************************************************************/
    559 
    560  rv = mgr->Clear();
    561  EXPECT_NS_SUCCEEDED(rv);
    562 
    563  /*******************************************************************
    564   *
    565   * Call GetNumberOfUndoItems() with an empty undo stack:
    566   *
    567   *******************************************************************/
    568 
    569  int32_t numitems;
    570  rv = mgr->GetNumberOfUndoItems(&numitems);
    571  EXPECT_NS_SUCCEEDED(rv);
    572  EXPECT_EQ(numitems, 0);
    573 
    574  /*******************************************************************
    575   *
    576   * Call GetNumberOfRedoItems() with an empty redo stack:
    577   *
    578   *******************************************************************/
    579 
    580  rv = mgr->GetNumberOfRedoItems(&numitems);
    581  EXPECT_NS_SUCCEEDED(rv);
    582  EXPECT_EQ(numitems, 0);
    583 
    584  /*******************************************************************
    585   *
    586   * Call PeekUndoStack() with an empty undo stack:
    587   *
    588   *******************************************************************/
    589 
    590  {
    591    nsCOMPtr<nsITransaction> tx;
    592    rv = mgr->PeekUndoStack(getter_AddRefs(tx));
    593    EXPECT_NS_SUCCEEDED(rv);
    594    EXPECT_EQ(tx, nullptr);
    595  }
    596 
    597  /*******************************************************************
    598   *
    599   * Call PeekRedoStack() with an empty undo stack:
    600   *
    601   *******************************************************************/
    602 
    603  {
    604    nsCOMPtr<nsITransaction> tx;
    605    rv = mgr->PeekRedoStack(getter_AddRefs(tx));
    606    EXPECT_NS_SUCCEEDED(rv);
    607    EXPECT_EQ(tx, nullptr);
    608  }
    609 
    610  /*******************************************************************
    611   *
    612   * Test coalescing by executing a transaction that can merge any
    613   * command into itself. Then execute 20 transaction. Afterwards,
    614   * we should still have the first transaction sitting on the undo
    615   * stack. Then clear the undo and redo stacks.
    616   *
    617   *******************************************************************/
    618 
    619  int32_t i;
    620  RefPtr<TestTransaction> tximpl;
    621  nsCOMPtr<nsITransaction> u1, u2, r1, r2;
    622 
    623  rv = mgr->SetMaxTransactionCount(10);
    624  EXPECT_NS_SUCCEEDED(rv);
    625 
    626  tximpl = factory->create(mgr, MERGE_FLAG);
    627  rv = mgr->DoTransaction(tximpl);
    628  EXPECT_NS_SUCCEEDED(rv);
    629 
    630  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
    631  EXPECT_NS_SUCCEEDED(rv);
    632  EXPECT_EQ(u1, tximpl);
    633 
    634  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
    635  EXPECT_NS_SUCCEEDED(rv);
    636 
    637  for (i = 1; i <= 20; i++) {
    638    tximpl = factory->create(mgr, NONE_FLAG);
    639    rv = mgr->DoTransaction(tximpl);
    640    EXPECT_NS_SUCCEEDED(rv);
    641  }
    642 
    643  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
    644  EXPECT_NS_SUCCEEDED(rv);
    645  EXPECT_EQ(u1, u2);
    646 
    647  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
    648  EXPECT_NS_SUCCEEDED(rv);
    649  EXPECT_EQ(r1, r2);
    650 
    651  rv = mgr->GetNumberOfUndoItems(&numitems);
    652  EXPECT_NS_SUCCEEDED(rv);
    653  EXPECT_EQ(numitems, 1);
    654 
    655  rv = mgr->GetNumberOfRedoItems(&numitems);
    656  EXPECT_NS_SUCCEEDED(rv);
    657  EXPECT_EQ(numitems, 0);
    658 
    659  rv = mgr->Clear();
    660  EXPECT_NS_SUCCEEDED(rv);
    661 
    662  /*******************************************************************
    663   *
    664   * Execute 20 transactions. Afterwards, we should have 10
    665   * transactions on the undo stack:
    666   *
    667   *******************************************************************/
    668 
    669  for (i = 1; i <= 20; i++) {
    670    tximpl = factory->create(mgr, NONE_FLAG);
    671    rv = mgr->DoTransaction(tximpl);
    672    EXPECT_NS_SUCCEEDED(rv);
    673  }
    674 
    675  rv = mgr->GetNumberOfUndoItems(&numitems);
    676  EXPECT_NS_SUCCEEDED(rv);
    677  EXPECT_EQ(numitems, 10);
    678 
    679  rv = mgr->GetNumberOfRedoItems(&numitems);
    680  EXPECT_NS_SUCCEEDED(rv);
    681  EXPECT_EQ(numitems, 0);
    682 
    683  /*******************************************************************
    684   *
    685   * Execute 20 transient transactions. Afterwards, we should still
    686   * have the same 10 transactions on the undo stack:
    687   *
    688   *******************************************************************/
    689 
    690  u1 = u2 = r1 = r2 = nullptr;
    691 
    692  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
    693  EXPECT_NS_SUCCEEDED(rv);
    694 
    695  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
    696  EXPECT_NS_SUCCEEDED(rv);
    697 
    698  for (i = 1; i <= 20; i++) {
    699    tximpl = factory->create(mgr, TRANSIENT_FLAG);
    700    rv = mgr->DoTransaction(tximpl);
    701    EXPECT_NS_SUCCEEDED(rv);
    702  }
    703 
    704  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
    705  EXPECT_NS_SUCCEEDED(rv);
    706  EXPECT_EQ(u1, u2);
    707 
    708  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
    709  EXPECT_NS_SUCCEEDED(rv);
    710  EXPECT_EQ(r1, r2);
    711 
    712  rv = mgr->GetNumberOfUndoItems(&numitems);
    713  EXPECT_NS_SUCCEEDED(rv);
    714  EXPECT_EQ(numitems, 10);
    715 
    716  rv = mgr->GetNumberOfRedoItems(&numitems);
    717  EXPECT_NS_SUCCEEDED(rv);
    718  EXPECT_EQ(numitems, 0);
    719 
    720  /*******************************************************************
    721   *
    722   * Undo 4 transactions. Afterwards, we should have 6 transactions
    723   * on the undo stack, and 4 on the redo stack:
    724   *
    725   *******************************************************************/
    726 
    727  for (i = 1; i <= 4; i++) {
    728    rv = mgr->UndoTransaction();
    729    EXPECT_NS_SUCCEEDED(rv);
    730  }
    731 
    732  rv = mgr->GetNumberOfUndoItems(&numitems);
    733  EXPECT_NS_SUCCEEDED(rv);
    734  EXPECT_EQ(numitems, 6);
    735 
    736  rv = mgr->GetNumberOfRedoItems(&numitems);
    737  EXPECT_NS_SUCCEEDED(rv);
    738  EXPECT_EQ(numitems, 4);
    739 
    740  /*******************************************************************
    741   *
    742   * Redo 2 transactions. Afterwards, we should have 8 transactions
    743   * on the undo stack, and 2 on the redo stack:
    744   *
    745   *******************************************************************/
    746 
    747  for (i = 1; i <= 2; ++i) {
    748    rv = mgr->RedoTransaction();
    749    EXPECT_NS_SUCCEEDED(rv);
    750  }
    751 
    752  rv = mgr->GetNumberOfUndoItems(&numitems);
    753  EXPECT_NS_SUCCEEDED(rv);
    754  EXPECT_EQ(numitems, 8);
    755 
    756  rv = mgr->GetNumberOfRedoItems(&numitems);
    757  EXPECT_NS_SUCCEEDED(rv);
    758  EXPECT_EQ(numitems, 2);
    759 
    760  /*******************************************************************
    761   *
    762   * Execute a new transaction. The redo stack should get pruned!
    763   *
    764   *******************************************************************/
    765 
    766  tximpl = factory->create(mgr, NONE_FLAG);
    767  rv = mgr->DoTransaction(tximpl);
    768  EXPECT_NS_SUCCEEDED(rv);
    769 
    770  rv = mgr->GetNumberOfUndoItems(&numitems);
    771  EXPECT_NS_SUCCEEDED(rv);
    772  EXPECT_EQ(numitems, 9);
    773 
    774  rv = mgr->GetNumberOfRedoItems(&numitems);
    775  EXPECT_NS_SUCCEEDED(rv);
    776  EXPECT_EQ(numitems, 0);
    777 
    778  /*******************************************************************
    779   *
    780   * Undo 4 transactions then clear the undo and redo stacks.
    781   *
    782   *******************************************************************/
    783 
    784  for (i = 1; i <= 4; ++i) {
    785    rv = mgr->UndoTransaction();
    786    EXPECT_NS_SUCCEEDED(rv);
    787  }
    788 
    789  rv = mgr->GetNumberOfUndoItems(&numitems);
    790  EXPECT_NS_SUCCEEDED(rv);
    791  EXPECT_EQ(numitems, 5);
    792 
    793  rv = mgr->GetNumberOfRedoItems(&numitems);
    794  EXPECT_NS_SUCCEEDED(rv);
    795  EXPECT_EQ(numitems, 4);
    796 
    797  rv = mgr->Clear();
    798  EXPECT_NS_SUCCEEDED(rv);
    799 
    800  rv = mgr->GetNumberOfUndoItems(&numitems);
    801  EXPECT_NS_SUCCEEDED(rv);
    802  EXPECT_EQ(numitems, 0);
    803 
    804  rv = mgr->GetNumberOfRedoItems(&numitems);
    805  EXPECT_NS_SUCCEEDED(rv);
    806  EXPECT_EQ(numitems, 0);
    807 
    808  /*******************************************************************
    809   *
    810   * Execute 5 transactions.
    811   *
    812   *******************************************************************/
    813 
    814  for (i = 1; i <= 5; i++) {
    815    tximpl = factory->create(mgr, NONE_FLAG);
    816    rv = mgr->DoTransaction(tximpl);
    817    EXPECT_NS_SUCCEEDED(rv);
    818  }
    819 
    820  rv = mgr->GetNumberOfUndoItems(&numitems);
    821  EXPECT_NS_SUCCEEDED(rv);
    822  EXPECT_EQ(numitems, 5);
    823 
    824  rv = mgr->GetNumberOfRedoItems(&numitems);
    825  EXPECT_NS_SUCCEEDED(rv);
    826  EXPECT_EQ(numitems, 0);
    827 
    828  /*******************************************************************
    829   *
    830   * Test transaction DoTransaction() error:
    831   *
    832   *******************************************************************/
    833 
    834  tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
    835 
    836  u1 = u2 = r1 = r2 = nullptr;
    837 
    838  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
    839  EXPECT_NS_SUCCEEDED(rv);
    840 
    841  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
    842  EXPECT_NS_SUCCEEDED(rv);
    843 
    844  rv = mgr->DoTransaction(tximpl);
    845  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    846 
    847  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
    848  EXPECT_NS_SUCCEEDED(rv);
    849  EXPECT_EQ(u1, u2);
    850 
    851  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
    852  EXPECT_NS_SUCCEEDED(rv);
    853  EXPECT_EQ(r1, r2);
    854 
    855  rv = mgr->GetNumberOfUndoItems(&numitems);
    856  EXPECT_NS_SUCCEEDED(rv);
    857  EXPECT_EQ(numitems, 5);
    858 
    859  rv = mgr->GetNumberOfRedoItems(&numitems);
    860  EXPECT_NS_SUCCEEDED(rv);
    861  EXPECT_EQ(numitems, 0);
    862 
    863  /*******************************************************************
    864   *
    865   * Test transaction UndoTransaction() error:
    866   *
    867   *******************************************************************/
    868 
    869  tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
    870  rv = mgr->DoTransaction(tximpl);
    871  EXPECT_NS_SUCCEEDED(rv);
    872 
    873  u1 = u2 = r1 = r2 = nullptr;
    874 
    875  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
    876  EXPECT_NS_SUCCEEDED(rv);
    877 
    878  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
    879  EXPECT_NS_SUCCEEDED(rv);
    880 
    881  rv = mgr->UndoTransaction();
    882  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    883 
    884  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
    885  EXPECT_NS_SUCCEEDED(rv);
    886  EXPECT_EQ(u1, u2);
    887 
    888  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
    889  EXPECT_NS_SUCCEEDED(rv);
    890  EXPECT_EQ(r1, r2);
    891 
    892  rv = mgr->GetNumberOfUndoItems(&numitems);
    893  EXPECT_NS_SUCCEEDED(rv);
    894  EXPECT_EQ(numitems, 6);
    895 
    896  rv = mgr->GetNumberOfRedoItems(&numitems);
    897  EXPECT_NS_SUCCEEDED(rv);
    898  EXPECT_EQ(numitems, 0);
    899 
    900  /*******************************************************************
    901   *
    902   * Test transaction RedoTransaction() error:
    903   *
    904   *******************************************************************/
    905 
    906  tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
    907  rv = mgr->DoTransaction(tximpl);
    908  EXPECT_NS_SUCCEEDED(rv);
    909 
    910  //
    911  // Execute a normal transaction to be used in a later test:
    912  //
    913 
    914  tximpl = factory->create(mgr, NONE_FLAG);
    915  rv = mgr->DoTransaction(tximpl);
    916  EXPECT_NS_SUCCEEDED(rv);
    917 
    918  //
    919  // Undo the 2 transactions just executed.
    920  //
    921 
    922  for (i = 1; i <= 2; ++i) {
    923    rv = mgr->UndoTransaction();
    924    EXPECT_NS_SUCCEEDED(rv);
    925  }
    926 
    927  //
    928  // The RedoErrorTransaction should now be at the top of the redo stack!
    929  //
    930 
    931  u1 = u2 = r1 = r2 = nullptr;
    932 
    933  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
    934  EXPECT_NS_SUCCEEDED(rv);
    935 
    936  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
    937  EXPECT_NS_SUCCEEDED(rv);
    938 
    939  rv = mgr->RedoTransaction();
    940  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    941 
    942  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
    943  EXPECT_NS_SUCCEEDED(rv);
    944  EXPECT_EQ(u1, u2);
    945 
    946  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
    947  EXPECT_NS_SUCCEEDED(rv);
    948  EXPECT_EQ(r1, r2);
    949 
    950  rv = mgr->GetNumberOfUndoItems(&numitems);
    951  EXPECT_NS_SUCCEEDED(rv);
    952  EXPECT_EQ(numitems, 6);
    953 
    954  rv = mgr->GetNumberOfRedoItems(&numitems);
    955  EXPECT_NS_SUCCEEDED(rv);
    956  EXPECT_EQ(numitems, 2);
    957 
    958  /*******************************************************************
    959   *
    960   * Make sure that setting the transaction manager's max transaction
    961   * count to zero, clears both the undo and redo stacks, and executes
    962   * all new commands without pushing them on the undo stack!
    963   *
    964   *******************************************************************/
    965 
    966  rv = mgr->SetMaxTransactionCount(0);
    967  EXPECT_NS_SUCCEEDED(rv);
    968 
    969  rv = mgr->GetNumberOfUndoItems(&numitems);
    970  EXPECT_NS_SUCCEEDED(rv);
    971  EXPECT_EQ(numitems, 0);
    972 
    973  rv = mgr->GetNumberOfRedoItems(&numitems);
    974  EXPECT_NS_SUCCEEDED(rv);
    975  EXPECT_EQ(numitems, 0);
    976 
    977  for (i = 1; i <= 20; i++) {
    978    tximpl = factory->create(mgr, NONE_FLAG);
    979    rv = mgr->DoTransaction(tximpl);
    980    EXPECT_NS_SUCCEEDED(rv);
    981 
    982    rv = mgr->GetNumberOfUndoItems(&numitems);
    983    EXPECT_NS_SUCCEEDED(rv);
    984    EXPECT_EQ(numitems, 0);
    985 
    986    rv = mgr->GetNumberOfRedoItems(&numitems);
    987    EXPECT_NS_SUCCEEDED(rv);
    988    EXPECT_EQ(numitems, 0);
    989  }
    990 
    991  /*******************************************************************
    992   *
    993   * Make sure that setting the transaction manager's max transaction
    994   * count to something greater than the number of transactions on
    995   * both the undo and redo stacks causes no pruning of the stacks:
    996   *
    997   *******************************************************************/
    998 
    999  rv = mgr->SetMaxTransactionCount(-1);
   1000  EXPECT_NS_SUCCEEDED(rv);
   1001 
   1002  // Push 20 transactions on the undo stack:
   1003 
   1004  for (i = 1; i <= 20; i++) {
   1005    tximpl = factory->create(mgr, NONE_FLAG);
   1006    rv = mgr->DoTransaction(tximpl);
   1007    EXPECT_NS_SUCCEEDED(rv);
   1008 
   1009    rv = mgr->GetNumberOfUndoItems(&numitems);
   1010    EXPECT_NS_SUCCEEDED(rv);
   1011    EXPECT_EQ(numitems, i);
   1012 
   1013    rv = mgr->GetNumberOfRedoItems(&numitems);
   1014    EXPECT_NS_SUCCEEDED(rv);
   1015    EXPECT_EQ(numitems, 0);
   1016  }
   1017 
   1018  for (i = 1; i <= 10; i++) {
   1019    rv = mgr->UndoTransaction();
   1020    EXPECT_NS_SUCCEEDED(rv);
   1021  }
   1022  rv = mgr->GetNumberOfUndoItems(&numitems);
   1023  EXPECT_NS_SUCCEEDED(rv);
   1024  EXPECT_EQ(numitems, 10);
   1025 
   1026  rv = mgr->GetNumberOfRedoItems(&numitems);
   1027  EXPECT_NS_SUCCEEDED(rv);
   1028  EXPECT_EQ(numitems, 10);
   1029 
   1030  u1 = u2 = r1 = r2 = nullptr;
   1031 
   1032  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
   1033  EXPECT_NS_SUCCEEDED(rv);
   1034 
   1035  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
   1036  EXPECT_NS_SUCCEEDED(rv);
   1037 
   1038  rv = mgr->SetMaxTransactionCount(25);
   1039  EXPECT_NS_SUCCEEDED(rv);
   1040 
   1041  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
   1042  EXPECT_NS_SUCCEEDED(rv);
   1043  EXPECT_EQ(u1, u2);
   1044 
   1045  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
   1046  EXPECT_NS_SUCCEEDED(rv);
   1047  EXPECT_EQ(r1, r2);
   1048 
   1049  rv = mgr->GetNumberOfUndoItems(&numitems);
   1050  EXPECT_NS_SUCCEEDED(rv);
   1051  EXPECT_EQ(numitems, 10);
   1052 
   1053  rv = mgr->GetNumberOfRedoItems(&numitems);
   1054  EXPECT_NS_SUCCEEDED(rv);
   1055  EXPECT_EQ(numitems, 10);
   1056 
   1057  /*******************************************************************
   1058   *
   1059   * Test undo stack pruning by setting the transaction
   1060   * manager's max transaction count to a number lower than the
   1061   * number of transactions on both the undo and redo stacks:
   1062   *
   1063   *******************************************************************/
   1064 
   1065  u1 = u2 = r1 = r2 = nullptr;
   1066 
   1067  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
   1068  EXPECT_NS_SUCCEEDED(rv);
   1069 
   1070  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
   1071  EXPECT_NS_SUCCEEDED(rv);
   1072 
   1073  rv = mgr->SetMaxTransactionCount(15);
   1074  EXPECT_NS_SUCCEEDED(rv);
   1075 
   1076  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
   1077  EXPECT_NS_SUCCEEDED(rv);
   1078  EXPECT_EQ(u1, u2);
   1079 
   1080  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
   1081  EXPECT_NS_SUCCEEDED(rv);
   1082  EXPECT_EQ(r1, r2);
   1083 
   1084  rv = mgr->GetNumberOfUndoItems(&numitems);
   1085  EXPECT_NS_SUCCEEDED(rv);
   1086  EXPECT_EQ(numitems, 5);
   1087 
   1088  rv = mgr->GetNumberOfRedoItems(&numitems);
   1089  EXPECT_NS_SUCCEEDED(rv);
   1090  EXPECT_EQ(numitems, 10);
   1091 
   1092  /*******************************************************************
   1093   *
   1094   * Test redo stack pruning by setting the transaction
   1095   * manager's max transaction count to a number lower than the
   1096   * number of transactions on both the undo and redo stacks:
   1097   *
   1098   *******************************************************************/
   1099 
   1100  u1 = u2 = r1 = r2 = nullptr;
   1101 
   1102  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
   1103  EXPECT_NS_SUCCEEDED(rv);
   1104 
   1105  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
   1106  EXPECT_NS_SUCCEEDED(rv);
   1107 
   1108  rv = mgr->SetMaxTransactionCount(5);
   1109  EXPECT_NS_SUCCEEDED(rv);
   1110 
   1111  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
   1112  EXPECT_NS_SUCCEEDED(rv);
   1113  EXPECT_FALSE(u2);
   1114 
   1115  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
   1116  EXPECT_NS_SUCCEEDED(rv);
   1117  EXPECT_EQ(r1, r2);
   1118 
   1119  rv = mgr->GetNumberOfUndoItems(&numitems);
   1120  EXPECT_NS_SUCCEEDED(rv);
   1121  EXPECT_EQ(numitems, 0);
   1122 
   1123  rv = mgr->GetNumberOfRedoItems(&numitems);
   1124  EXPECT_NS_SUCCEEDED(rv);
   1125  EXPECT_EQ(numitems, 5);
   1126 
   1127  /*******************************************************************
   1128   *
   1129   * Release the transaction manager. Any transactions on the undo
   1130   * and redo stack should automatically be released:
   1131   *
   1132   *******************************************************************/
   1133 
   1134  rv = mgr->SetMaxTransactionCount(-1);
   1135  EXPECT_NS_SUCCEEDED(rv);
   1136 
   1137  // Push 20 transactions on the undo stack:
   1138 
   1139  for (i = 1; i <= 20; i++) {
   1140    tximpl = factory->create(mgr, NONE_FLAG);
   1141    rv = mgr->DoTransaction(tximpl);
   1142    EXPECT_NS_SUCCEEDED(rv);
   1143 
   1144    rv = mgr->GetNumberOfUndoItems(&numitems);
   1145    EXPECT_NS_SUCCEEDED(rv);
   1146    EXPECT_EQ(numitems, i);
   1147 
   1148    rv = mgr->GetNumberOfRedoItems(&numitems);
   1149    EXPECT_NS_SUCCEEDED(rv);
   1150    EXPECT_EQ(numitems, 0);
   1151  }
   1152 
   1153  for (i = 1; i <= 10; i++) {
   1154    rv = mgr->UndoTransaction();
   1155    EXPECT_NS_SUCCEEDED(rv);
   1156  }
   1157 
   1158  rv = mgr->GetNumberOfUndoItems(&numitems);
   1159  EXPECT_NS_SUCCEEDED(rv);
   1160  EXPECT_EQ(numitems, 10);
   1161 
   1162  rv = mgr->GetNumberOfRedoItems(&numitems);
   1163  EXPECT_NS_SUCCEEDED(rv);
   1164  EXPECT_EQ(numitems, 10);
   1165 
   1166  rv = mgr->Clear();
   1167  EXPECT_NS_SUCCEEDED(rv);
   1168 }
   1169 
   1170 TEST(TestTXMgr, SimpleTest)
   1171 {
   1172  /*******************************************************************
   1173   *
   1174   * Initialize globals for test.
   1175   *
   1176   *******************************************************************/
   1177  reset_globals();
   1178  sDoOrderArr = sSimpleTestDoOrderArr;
   1179  sUndoOrderArr = sSimpleTestUndoOrderArr;
   1180  sRedoOrderArr = sSimpleTestRedoOrderArr;
   1181 
   1182  /*******************************************************************
   1183   *
   1184   * Run the quick test.
   1185   *
   1186   *******************************************************************/
   1187 
   1188  SimpleTransactionFactory factory;
   1189 
   1190  quick_test(&factory);
   1191 }
   1192 
   1193 TEST(TestTXMgr, AggregationTest)
   1194 {
   1195  /*******************************************************************
   1196   *
   1197   * Initialize globals for test.
   1198   *
   1199   *******************************************************************/
   1200 
   1201  reset_globals();
   1202  sDoOrderArr = sAggregateTestDoOrderArr;
   1203  sUndoOrderArr = sAggregateTestUndoOrderArr;
   1204  sRedoOrderArr = sAggregateTestRedoOrderArr;
   1205 
   1206  /*******************************************************************
   1207   *
   1208   * Run the quick test.
   1209   *
   1210   *******************************************************************/
   1211 
   1212  AggregateTransactionFactory factory(3, 2);
   1213 
   1214  quick_test(&factory);
   1215 }
   1216 
   1217 /**
   1218 * Test behaviors in batch mode.
   1219 **/
   1220 MOZ_CAN_RUN_SCRIPT_BOUNDARY void quick_batch_test(
   1221    TestTransactionFactory* factory) {
   1222  /*******************************************************************
   1223   *
   1224   * Create a transaction manager implementation:
   1225   *
   1226   *******************************************************************/
   1227 
   1228  nsCOMPtr<nsITransactionManager> mgr = new TransactionManager();
   1229 
   1230  int32_t numitems;
   1231 
   1232  /*******************************************************************
   1233   *
   1234   * Make sure an unbalanced call to EndBatch(false) with empty undo stack
   1235   * throws an error!
   1236   *
   1237   *******************************************************************/
   1238 
   1239  nsresult rv = mgr->GetNumberOfUndoItems(&numitems);
   1240  EXPECT_NS_SUCCEEDED(rv);
   1241  EXPECT_EQ(numitems, 0);
   1242 
   1243  rv = mgr->EndBatch(false);
   1244  EXPECT_EQ(rv, NS_ERROR_FAILURE);
   1245 
   1246  rv = mgr->GetNumberOfUndoItems(&numitems);
   1247  EXPECT_NS_SUCCEEDED(rv);
   1248  EXPECT_EQ(numitems, 0);
   1249 
   1250  /*******************************************************************
   1251   *
   1252   * Make sure that an empty batch is not added to the undo stack
   1253   * when it is closed.
   1254   *
   1255   *******************************************************************/
   1256 
   1257  rv = mgr->GetNumberOfUndoItems(&numitems);
   1258  EXPECT_NS_SUCCEEDED(rv);
   1259  EXPECT_EQ(numitems, 0);
   1260 
   1261  rv = mgr->BeginBatch(nullptr);
   1262  EXPECT_NS_SUCCEEDED(rv);
   1263 
   1264  rv = mgr->GetNumberOfUndoItems(&numitems);
   1265  EXPECT_NS_SUCCEEDED(rv);
   1266  EXPECT_EQ(numitems, 0);
   1267 
   1268  rv = mgr->EndBatch(false);
   1269  EXPECT_NS_SUCCEEDED(rv);
   1270 
   1271  rv = mgr->GetNumberOfUndoItems(&numitems);
   1272  EXPECT_NS_SUCCEEDED(rv);
   1273  EXPECT_EQ(numitems, 0);
   1274 
   1275  int32_t i;
   1276  RefPtr<TestTransaction> tximpl;
   1277 
   1278  /*******************************************************************
   1279   *
   1280   * Execute 20 transactions. Afterwards, we should have 1
   1281   * transaction on the undo stack:
   1282   *
   1283   *******************************************************************/
   1284 
   1285  rv = mgr->BeginBatch(nullptr);
   1286  EXPECT_NS_SUCCEEDED(rv);
   1287 
   1288  for (i = 1; i <= 20; i++) {
   1289    tximpl = factory->create(mgr, NONE_FLAG);
   1290    rv = mgr->DoTransaction(tximpl);
   1291    EXPECT_NS_SUCCEEDED(rv);
   1292  }
   1293 
   1294  rv = mgr->GetNumberOfUndoItems(&numitems);
   1295  EXPECT_NS_SUCCEEDED(rv);
   1296  EXPECT_EQ(numitems, 0);
   1297 
   1298  rv = mgr->EndBatch(false);
   1299  EXPECT_NS_SUCCEEDED(rv);
   1300 
   1301  rv = mgr->GetNumberOfUndoItems(&numitems);
   1302  EXPECT_NS_SUCCEEDED(rv);
   1303  EXPECT_EQ(numitems, 1);
   1304 
   1305  nsCOMPtr<nsITransaction> u1, u2, r1, r2;
   1306 
   1307  /*******************************************************************
   1308   *
   1309   * Execute 20 transient transactions. Afterwards, we should still
   1310   * have the same transaction on the undo stack:
   1311   *
   1312   *******************************************************************/
   1313 
   1314  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
   1315  EXPECT_NS_SUCCEEDED(rv);
   1316 
   1317  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
   1318  EXPECT_NS_SUCCEEDED(rv);
   1319 
   1320  rv = mgr->BeginBatch(nullptr);
   1321  EXPECT_NS_SUCCEEDED(rv);
   1322 
   1323  for (i = 1; i <= 20; i++) {
   1324    tximpl = factory->create(mgr, TRANSIENT_FLAG);
   1325    rv = mgr->DoTransaction(tximpl);
   1326    EXPECT_NS_SUCCEEDED(rv);
   1327  }
   1328 
   1329  rv = mgr->EndBatch(false);
   1330  EXPECT_NS_SUCCEEDED(rv);
   1331 
   1332  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
   1333  EXPECT_NS_SUCCEEDED(rv);
   1334  EXPECT_EQ(u1, u2);
   1335 
   1336  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
   1337  EXPECT_NS_SUCCEEDED(rv);
   1338  EXPECT_EQ(r1, r2);
   1339 
   1340  rv = mgr->GetNumberOfUndoItems(&numitems);
   1341  EXPECT_NS_SUCCEEDED(rv);
   1342  EXPECT_EQ(numitems, 1);
   1343 
   1344  rv = mgr->GetNumberOfRedoItems(&numitems);
   1345  EXPECT_NS_SUCCEEDED(rv);
   1346  EXPECT_EQ(numitems, 0);
   1347 
   1348  /*******************************************************************
   1349   *
   1350   * Test nested batching. Afterwards, we should have 2 transactions
   1351   * on the undo stack:
   1352   *
   1353   *******************************************************************/
   1354 
   1355  rv = mgr->BeginBatch(nullptr);
   1356  EXPECT_NS_SUCCEEDED(rv);
   1357 
   1358  tximpl = factory->create(mgr, NONE_FLAG);
   1359  rv = mgr->DoTransaction(tximpl);
   1360  EXPECT_NS_SUCCEEDED(rv);
   1361 
   1362  rv = mgr->GetNumberOfUndoItems(&numitems);
   1363  EXPECT_NS_SUCCEEDED(rv);
   1364  EXPECT_EQ(numitems, 1);
   1365 
   1366  rv = mgr->BeginBatch(nullptr);
   1367  EXPECT_NS_SUCCEEDED(rv);
   1368 
   1369  tximpl = factory->create(mgr, NONE_FLAG);
   1370  rv = mgr->DoTransaction(tximpl);
   1371  EXPECT_NS_SUCCEEDED(rv);
   1372 
   1373  rv = mgr->GetNumberOfUndoItems(&numitems);
   1374  EXPECT_NS_SUCCEEDED(rv);
   1375  EXPECT_EQ(numitems, 1);
   1376 
   1377  rv = mgr->BeginBatch(nullptr);
   1378  EXPECT_NS_SUCCEEDED(rv);
   1379 
   1380  tximpl = factory->create(mgr, NONE_FLAG);
   1381  rv = mgr->DoTransaction(tximpl);
   1382  EXPECT_NS_SUCCEEDED(rv);
   1383 
   1384  rv = mgr->GetNumberOfUndoItems(&numitems);
   1385  EXPECT_NS_SUCCEEDED(rv);
   1386  EXPECT_EQ(numitems, 1);
   1387 
   1388  rv = mgr->EndBatch(false);
   1389  EXPECT_NS_SUCCEEDED(rv);
   1390 
   1391  rv = mgr->EndBatch(false);
   1392  EXPECT_NS_SUCCEEDED(rv);
   1393 
   1394  rv = mgr->EndBatch(false);
   1395  EXPECT_NS_SUCCEEDED(rv);
   1396 
   1397  rv = mgr->GetNumberOfUndoItems(&numitems);
   1398  EXPECT_NS_SUCCEEDED(rv);
   1399  EXPECT_EQ(numitems, 2);
   1400 
   1401  /*******************************************************************
   1402   *
   1403   * Undo 2 batch transactions. Afterwards, we should have 0
   1404   * transactions on the undo stack and 2 on the redo stack.
   1405   *
   1406   *******************************************************************/
   1407 
   1408  for (i = 1; i <= 2; ++i) {
   1409    rv = mgr->UndoTransaction();
   1410    EXPECT_NS_SUCCEEDED(rv);
   1411  }
   1412 
   1413  rv = mgr->GetNumberOfUndoItems(&numitems);
   1414  EXPECT_NS_SUCCEEDED(rv);
   1415  EXPECT_EQ(numitems, 0);
   1416 
   1417  rv = mgr->GetNumberOfRedoItems(&numitems);
   1418  EXPECT_NS_SUCCEEDED(rv);
   1419  EXPECT_EQ(numitems, 2);
   1420 
   1421  /*******************************************************************
   1422   *
   1423   * Redo 2 batch transactions. Afterwards, we should have 2
   1424   * transactions on the undo stack and 0 on the redo stack.
   1425   *
   1426   *******************************************************************/
   1427 
   1428  for (i = 1; i <= 2; ++i) {
   1429    rv = mgr->RedoTransaction();
   1430    EXPECT_NS_SUCCEEDED(rv);
   1431  }
   1432 
   1433  rv = mgr->GetNumberOfUndoItems(&numitems);
   1434  EXPECT_NS_SUCCEEDED(rv);
   1435  EXPECT_EQ(numitems, 2);
   1436 
   1437  rv = mgr->GetNumberOfRedoItems(&numitems);
   1438  EXPECT_NS_SUCCEEDED(rv);
   1439  EXPECT_EQ(numitems, 0);
   1440 
   1441  /*******************************************************************
   1442   *
   1443   * Call undo. Afterwards, we should have 1 transaction
   1444   * on the undo stack, and 1 on the redo stack:
   1445   *
   1446   *******************************************************************/
   1447 
   1448  rv = mgr->UndoTransaction();
   1449  EXPECT_NS_SUCCEEDED(rv);
   1450 
   1451  rv = mgr->GetNumberOfUndoItems(&numitems);
   1452  EXPECT_NS_SUCCEEDED(rv);
   1453  EXPECT_EQ(numitems, 1);
   1454 
   1455  rv = mgr->GetNumberOfRedoItems(&numitems);
   1456  EXPECT_NS_SUCCEEDED(rv);
   1457  EXPECT_EQ(numitems, 1);
   1458 
   1459  /*******************************************************************
   1460   *
   1461   * Make sure an unbalanced call to EndBatch(false) throws an error and
   1462   * doesn't affect the undo and redo stacks!
   1463   *
   1464   *******************************************************************/
   1465 
   1466  rv = mgr->EndBatch(false);
   1467  EXPECT_EQ(rv, NS_ERROR_FAILURE);
   1468 
   1469  rv = mgr->GetNumberOfUndoItems(&numitems);
   1470  EXPECT_NS_SUCCEEDED(rv);
   1471  EXPECT_EQ(numitems, 1);
   1472 
   1473  rv = mgr->GetNumberOfRedoItems(&numitems);
   1474  EXPECT_NS_SUCCEEDED(rv);
   1475  EXPECT_EQ(numitems, 1);
   1476 
   1477  /*******************************************************************
   1478   *
   1479   * Make sure that an empty batch is not added to the undo stack
   1480   * when it is closed, and that it does not affect the undo and redo
   1481   * stacks.
   1482   *
   1483   *******************************************************************/
   1484 
   1485  rv = mgr->BeginBatch(nullptr);
   1486  EXPECT_NS_SUCCEEDED(rv);
   1487 
   1488  rv = mgr->GetNumberOfUndoItems(&numitems);
   1489  EXPECT_NS_SUCCEEDED(rv);
   1490  EXPECT_EQ(numitems, 1);
   1491 
   1492  rv = mgr->GetNumberOfRedoItems(&numitems);
   1493  EXPECT_NS_SUCCEEDED(rv);
   1494  EXPECT_EQ(numitems, 1);
   1495 
   1496  rv = mgr->EndBatch(false);
   1497  EXPECT_NS_SUCCEEDED(rv);
   1498 
   1499  rv = mgr->GetNumberOfUndoItems(&numitems);
   1500  EXPECT_NS_SUCCEEDED(rv);
   1501  EXPECT_EQ(numitems, 1);
   1502 
   1503  rv = mgr->GetNumberOfRedoItems(&numitems);
   1504  EXPECT_NS_SUCCEEDED(rv);
   1505  EXPECT_EQ(numitems, 1);
   1506 
   1507  /*******************************************************************
   1508   *
   1509   * Execute a new transaction. The redo stack should get pruned!
   1510   *
   1511   *******************************************************************/
   1512 
   1513  rv = mgr->BeginBatch(nullptr);
   1514  EXPECT_NS_SUCCEEDED(rv);
   1515 
   1516  for (i = 1; i <= 20; i++) {
   1517    tximpl = factory->create(mgr, NONE_FLAG);
   1518    rv = mgr->DoTransaction(tximpl);
   1519    EXPECT_NS_SUCCEEDED(rv);
   1520  }
   1521 
   1522  rv = mgr->GetNumberOfUndoItems(&numitems);
   1523  EXPECT_NS_SUCCEEDED(rv);
   1524  EXPECT_EQ(numitems, 1);
   1525 
   1526  rv = mgr->GetNumberOfRedoItems(&numitems);
   1527  EXPECT_NS_SUCCEEDED(rv);
   1528  EXPECT_EQ(numitems, 1);
   1529 
   1530  rv = mgr->EndBatch(false);
   1531  EXPECT_NS_SUCCEEDED(rv);
   1532 
   1533  rv = mgr->GetNumberOfUndoItems(&numitems);
   1534  EXPECT_NS_SUCCEEDED(rv);
   1535  EXPECT_EQ(numitems, 2);
   1536 
   1537  rv = mgr->GetNumberOfRedoItems(&numitems);
   1538  EXPECT_NS_SUCCEEDED(rv);
   1539  EXPECT_EQ(numitems, 0);
   1540 
   1541  /*******************************************************************
   1542   *
   1543   * Call undo.
   1544   *
   1545   *******************************************************************/
   1546 
   1547  // Move a transaction over to the redo stack, so that we have one
   1548  // transaction on the undo stack, and one on the redo stack!
   1549 
   1550  rv = mgr->UndoTransaction();
   1551  EXPECT_NS_SUCCEEDED(rv);
   1552 
   1553  rv = mgr->GetNumberOfUndoItems(&numitems);
   1554  EXPECT_NS_SUCCEEDED(rv);
   1555  EXPECT_EQ(numitems, 1);
   1556 
   1557  rv = mgr->GetNumberOfRedoItems(&numitems);
   1558  EXPECT_NS_SUCCEEDED(rv);
   1559  EXPECT_EQ(numitems, 1);
   1560 
   1561  /*******************************************************************
   1562   *
   1563   * Test transaction DoTransaction() error:
   1564   *
   1565   *******************************************************************/
   1566 
   1567  tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
   1568 
   1569  u1 = u2 = r1 = r2 = nullptr;
   1570 
   1571  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
   1572  EXPECT_NS_SUCCEEDED(rv);
   1573 
   1574  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
   1575  EXPECT_NS_SUCCEEDED(rv);
   1576 
   1577  rv = mgr->BeginBatch(nullptr);
   1578  EXPECT_NS_SUCCEEDED(rv);
   1579 
   1580  rv = mgr->DoTransaction(tximpl);
   1581  EXPECT_EQ(rv, NS_ERROR_FAILURE);
   1582 
   1583  rv = mgr->EndBatch(false);
   1584  EXPECT_NS_SUCCEEDED(rv);
   1585 
   1586  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
   1587  EXPECT_NS_SUCCEEDED(rv);
   1588  EXPECT_EQ(u1, u2);
   1589 
   1590  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
   1591  EXPECT_NS_SUCCEEDED(rv);
   1592  EXPECT_EQ(r1, r2);
   1593 
   1594  rv = mgr->GetNumberOfUndoItems(&numitems);
   1595  EXPECT_NS_SUCCEEDED(rv);
   1596  EXPECT_EQ(numitems, 1);
   1597 
   1598  rv = mgr->GetNumberOfRedoItems(&numitems);
   1599  EXPECT_NS_SUCCEEDED(rv);
   1600  EXPECT_EQ(numitems, 1);
   1601 
   1602  /*******************************************************************
   1603   *
   1604   * Test transaction UndoTransaction() error:
   1605   *
   1606   *******************************************************************/
   1607 
   1608  tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
   1609 
   1610  rv = mgr->BeginBatch(nullptr);
   1611  EXPECT_NS_SUCCEEDED(rv);
   1612 
   1613  rv = mgr->DoTransaction(tximpl);
   1614  EXPECT_NS_SUCCEEDED(rv);
   1615 
   1616  rv = mgr->EndBatch(false);
   1617  EXPECT_NS_SUCCEEDED(rv);
   1618 
   1619  u1 = u2 = r1 = r2 = nullptr;
   1620 
   1621  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
   1622  EXPECT_NS_SUCCEEDED(rv);
   1623 
   1624  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
   1625  EXPECT_NS_SUCCEEDED(rv);
   1626 
   1627  rv = mgr->UndoTransaction();
   1628  EXPECT_EQ(rv, NS_ERROR_FAILURE);
   1629 
   1630  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
   1631  EXPECT_NS_SUCCEEDED(rv);
   1632  EXPECT_EQ(u1, u2);
   1633 
   1634  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
   1635  EXPECT_NS_SUCCEEDED(rv);
   1636  EXPECT_EQ(r1, r2);
   1637 
   1638  rv = mgr->GetNumberOfUndoItems(&numitems);
   1639  EXPECT_NS_SUCCEEDED(rv);
   1640  EXPECT_EQ(numitems, 2);
   1641 
   1642  rv = mgr->GetNumberOfRedoItems(&numitems);
   1643  EXPECT_NS_SUCCEEDED(rv);
   1644  EXPECT_EQ(numitems, 0);
   1645 
   1646  /*******************************************************************
   1647   *
   1648   * Test transaction RedoTransaction() error:
   1649   *
   1650   *******************************************************************/
   1651 
   1652  tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
   1653 
   1654  rv = mgr->BeginBatch(nullptr);
   1655  EXPECT_NS_SUCCEEDED(rv);
   1656 
   1657  rv = mgr->DoTransaction(tximpl);
   1658  EXPECT_NS_SUCCEEDED(rv);
   1659 
   1660  rv = mgr->EndBatch(false);
   1661  EXPECT_NS_SUCCEEDED(rv);
   1662 
   1663  //
   1664  // Execute a normal transaction to be used in a later test:
   1665  //
   1666 
   1667  tximpl = factory->create(mgr, NONE_FLAG);
   1668  rv = mgr->DoTransaction(tximpl);
   1669  EXPECT_NS_SUCCEEDED(rv);
   1670 
   1671  //
   1672  // Undo the 2 transactions just executed.
   1673  //
   1674 
   1675  for (i = 1; i <= 2; ++i) {
   1676    rv = mgr->UndoTransaction();
   1677    EXPECT_NS_SUCCEEDED(rv);
   1678  }
   1679 
   1680  //
   1681  // The RedoErrorTransaction should now be at the top of the redo stack!
   1682  //
   1683 
   1684  u1 = u2 = r1 = r2 = nullptr;
   1685 
   1686  rv = mgr->PeekUndoStack(getter_AddRefs(u1));
   1687  EXPECT_NS_SUCCEEDED(rv);
   1688 
   1689  rv = mgr->PeekRedoStack(getter_AddRefs(r1));
   1690  EXPECT_NS_SUCCEEDED(rv);
   1691 
   1692  rv = mgr->RedoTransaction();
   1693  EXPECT_EQ(rv, NS_ERROR_FAILURE);
   1694 
   1695  rv = mgr->PeekUndoStack(getter_AddRefs(u2));
   1696  EXPECT_NS_SUCCEEDED(rv);
   1697  EXPECT_EQ(u1, u2);
   1698 
   1699  rv = mgr->PeekRedoStack(getter_AddRefs(r2));
   1700  EXPECT_NS_SUCCEEDED(rv);
   1701  EXPECT_EQ(r1, r2);
   1702 
   1703  rv = mgr->GetNumberOfUndoItems(&numitems);
   1704  EXPECT_NS_SUCCEEDED(rv);
   1705  EXPECT_EQ(numitems, 2);
   1706 
   1707  rv = mgr->GetNumberOfRedoItems(&numitems);
   1708  EXPECT_NS_SUCCEEDED(rv);
   1709  EXPECT_EQ(numitems, 2);
   1710 
   1711  /*******************************************************************
   1712   *
   1713   * Make sure that setting the transaction manager's max transaction
   1714   * count to zero, clears both the undo and redo stacks, and executes
   1715   * all new commands without pushing them on the undo stack!
   1716   *
   1717   *******************************************************************/
   1718 
   1719  rv = mgr->SetMaxTransactionCount(0);
   1720  EXPECT_NS_SUCCEEDED(rv);
   1721 
   1722  rv = mgr->GetNumberOfUndoItems(&numitems);
   1723  EXPECT_NS_SUCCEEDED(rv);
   1724  EXPECT_EQ(numitems, 0);
   1725 
   1726  rv = mgr->GetNumberOfRedoItems(&numitems);
   1727  EXPECT_NS_SUCCEEDED(rv);
   1728  EXPECT_EQ(numitems, 0);
   1729 
   1730  for (i = 1; i <= 20; i++) {
   1731    tximpl = factory->create(mgr, NONE_FLAG);
   1732 
   1733    rv = mgr->BeginBatch(nullptr);
   1734    EXPECT_NS_SUCCEEDED(rv);
   1735 
   1736    rv = mgr->DoTransaction(tximpl);
   1737    EXPECT_NS_SUCCEEDED(rv);
   1738 
   1739    rv = mgr->EndBatch(false);
   1740    EXPECT_NS_SUCCEEDED(rv);
   1741 
   1742    rv = mgr->GetNumberOfUndoItems(&numitems);
   1743    EXPECT_NS_SUCCEEDED(rv);
   1744    EXPECT_EQ(numitems, 0);
   1745 
   1746    rv = mgr->GetNumberOfRedoItems(&numitems);
   1747    EXPECT_NS_SUCCEEDED(rv);
   1748    EXPECT_EQ(numitems, 0);
   1749  }
   1750 
   1751  /*******************************************************************
   1752   *
   1753   * Release the transaction manager. Any transactions on the undo
   1754   * and redo stack should automatically be released:
   1755   *
   1756   *******************************************************************/
   1757 
   1758  rv = mgr->SetMaxTransactionCount(-1);
   1759  EXPECT_NS_SUCCEEDED(rv);
   1760 
   1761  // Push 20 transactions on the undo stack:
   1762 
   1763  for (i = 1; i <= 20; i++) {
   1764    tximpl = factory->create(mgr, NONE_FLAG);
   1765 
   1766    rv = mgr->BeginBatch(nullptr);
   1767    EXPECT_NS_SUCCEEDED(rv);
   1768 
   1769    rv = mgr->DoTransaction(tximpl);
   1770    EXPECT_NS_SUCCEEDED(rv);
   1771 
   1772    rv = mgr->EndBatch(false);
   1773    EXPECT_NS_SUCCEEDED(rv);
   1774 
   1775    rv = mgr->GetNumberOfUndoItems(&numitems);
   1776    EXPECT_NS_SUCCEEDED(rv);
   1777    EXPECT_EQ(numitems, i);
   1778 
   1779    rv = mgr->GetNumberOfRedoItems(&numitems);
   1780    EXPECT_NS_SUCCEEDED(rv);
   1781    EXPECT_EQ(numitems, 0);
   1782  }
   1783 
   1784  for (i = 1; i <= 10; i++) {
   1785    rv = mgr->UndoTransaction();
   1786    EXPECT_NS_SUCCEEDED(rv);
   1787  }
   1788  rv = mgr->GetNumberOfUndoItems(&numitems);
   1789  EXPECT_NS_SUCCEEDED(rv);
   1790  EXPECT_EQ(numitems, 10);
   1791 
   1792  rv = mgr->GetNumberOfRedoItems(&numitems);
   1793  EXPECT_NS_SUCCEEDED(rv);
   1794  EXPECT_EQ(numitems, 10);
   1795 
   1796  rv = mgr->Clear();
   1797  EXPECT_NS_SUCCEEDED(rv);
   1798 }
   1799 
   1800 TEST(TestTXMgr, SimpleBatchTest)
   1801 {
   1802  /*******************************************************************
   1803   *
   1804   * Initialize globals for test.
   1805   *
   1806   *******************************************************************/
   1807  reset_globals();
   1808  sDoOrderArr = sSimpleBatchTestDoOrderArr;
   1809  sUndoOrderArr = sSimpleBatchTestUndoOrderArr;
   1810  sRedoOrderArr = sSimpleBatchTestRedoOrderArr;
   1811 
   1812  /*******************************************************************
   1813   *
   1814   * Run the quick batch test.
   1815   *
   1816   *******************************************************************/
   1817 
   1818  SimpleTransactionFactory factory;
   1819  quick_batch_test(&factory);
   1820 }
   1821 
   1822 TEST(TestTXMgr, AggregationBatchTest)
   1823 {
   1824  /*******************************************************************
   1825   *
   1826   * Initialize globals for test.
   1827   *
   1828   *******************************************************************/
   1829 
   1830  reset_globals();
   1831  sDoOrderArr = sAggregateBatchTestDoOrderArr;
   1832  sUndoOrderArr = sAggregateBatchTestUndoOrderArr;
   1833  sRedoOrderArr = sAggregateBatchTestRedoOrderArr;
   1834 
   1835  /*******************************************************************
   1836   *
   1837   * Run the quick batch test.
   1838   *
   1839   *******************************************************************/
   1840 
   1841  AggregateTransactionFactory factory(3, 2, BATCH_FLAG);
   1842 
   1843  quick_batch_test(&factory);
   1844 }
   1845 
   1846 /**
   1847 * Create 'iterations * (iterations + 1) / 2' transactions;
   1848 * do/undo/redo/undo them.
   1849 **/
   1850 MOZ_CAN_RUN_SCRIPT_BOUNDARY void stress_test(TestTransactionFactory* factory,
   1851                                             int32_t iterations) {
   1852  /*******************************************************************
   1853   *
   1854   * Create a transaction manager:
   1855   *
   1856   *******************************************************************/
   1857 
   1858  nsCOMPtr<nsITransactionManager> mgr = new TransactionManager();
   1859 
   1860  nsresult rv;
   1861  int32_t i, j;
   1862 
   1863  for (i = 1; i <= iterations; i++) {
   1864    /*******************************************************************
   1865     *
   1866     * Create and execute a bunch of transactions:
   1867     *
   1868     *******************************************************************/
   1869 
   1870    for (j = 1; j <= i; j++) {
   1871      RefPtr<TestTransaction> tximpl = factory->create(mgr, NONE_FLAG);
   1872      rv = mgr->DoTransaction(tximpl);
   1873      EXPECT_NS_SUCCEEDED(rv);
   1874    }
   1875 
   1876    /*******************************************************************
   1877     *
   1878     * Undo all the transactions:
   1879     *
   1880     *******************************************************************/
   1881 
   1882    for (j = 1; j <= i; j++) {
   1883      rv = mgr->UndoTransaction();
   1884      EXPECT_NS_SUCCEEDED(rv);
   1885    }
   1886 
   1887    /*******************************************************************
   1888     *
   1889     * Redo all the transactions:
   1890     *
   1891     *******************************************************************/
   1892 
   1893    for (j = 1; j <= i; j++) {
   1894      rv = mgr->RedoTransaction();
   1895      EXPECT_NS_SUCCEEDED(rv);
   1896    }
   1897 
   1898    /*******************************************************************
   1899     *
   1900     * Undo all the transactions again so that they all end up on
   1901     * the redo stack for pruning the next time we execute a new
   1902     * transaction
   1903     *
   1904     *******************************************************************/
   1905 
   1906    for (j = 1; j <= i; j++) {
   1907      rv = mgr->UndoTransaction();
   1908      EXPECT_NS_SUCCEEDED(rv);
   1909    }
   1910  }
   1911 
   1912  rv = mgr->Clear();
   1913  EXPECT_NS_SUCCEEDED(rv);
   1914 }
   1915 
   1916 TEST(TestTXMgr, SimpleStressTest)
   1917 {
   1918  /*******************************************************************
   1919   *
   1920   * Initialize globals for test.
   1921   *
   1922   *******************************************************************/
   1923 
   1924  reset_globals();
   1925 
   1926  /*******************************************************************
   1927   *
   1928   * Do the stress test:
   1929   *
   1930   *******************************************************************/
   1931 
   1932  SimpleTransactionFactory factory;
   1933 
   1934  int32_t iterations =
   1935 #ifdef DEBUG
   1936      10
   1937 #else
   1938      //
   1939      // 1500 iterations sends 1,125,750 transactions through the system!!
   1940      //
   1941      1500
   1942 #endif
   1943      ;
   1944  stress_test(&factory, iterations);
   1945 }
   1946 
   1947 TEST(TestTXMgr, AggregationStressTest)
   1948 {
   1949  /*******************************************************************
   1950   *
   1951   * Initialize globals for test.
   1952   *
   1953   *******************************************************************/
   1954 
   1955  reset_globals();
   1956 
   1957  /*******************************************************************
   1958   *
   1959   * Do the stress test:
   1960   *
   1961   *******************************************************************/
   1962 
   1963  AggregateTransactionFactory factory(3, 4);
   1964 
   1965  int32_t iterations =
   1966 #ifdef DEBUG
   1967      10
   1968 #else
   1969      //
   1970      // 500 iterations sends 2,630,250 transactions through the system!!
   1971      //
   1972      500
   1973 #endif
   1974      ;
   1975  stress_test(&factory, iterations);
   1976 }
   1977 
   1978 TEST(TestTXMgr, AggregationBatchStressTest)
   1979 {
   1980  /*******************************************************************
   1981   *
   1982   * Initialize globals for test.
   1983   *
   1984   *******************************************************************/
   1985 
   1986  reset_globals();
   1987 
   1988  /*******************************************************************
   1989   *
   1990   * Do the stress test:
   1991   *
   1992   *******************************************************************/
   1993 
   1994  AggregateTransactionFactory factory(3, 4, BATCH_FLAG);
   1995 
   1996  int32_t iterations =
   1997 #ifdef DEBUG
   1998      10
   1999 #else
   2000 #  if defined(MOZ_ASAN) || defined(MOZ_WIDGET_ANDROID)
   2001      // See Bug 929985: 500 is too many for ASAN and Android, 100 is safe.
   2002      100
   2003 #  else
   2004      //
   2005      // 500 iterations sends 2,630,250 transactions through the system!!
   2006      //
   2007      500
   2008 #  endif
   2009 #endif
   2010      ;
   2011  stress_test(&factory, iterations);
   2012 }