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