| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <vector> | 5 #include <vector> |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/eintr_wrapper.h" | 10 #include "base/eintr_wrapper.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
| 14 #include "base/run_loop.h" |
| 14 #include "base/thread_task_runner_handle.h" | 15 #include "base/thread_task_runner_handle.h" |
| 15 #include "base/threading/platform_thread.h" | 16 #include "base/threading/platform_thread.h" |
| 16 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 19 |
| 19 #if defined(OS_WIN) | 20 #if defined(OS_WIN) |
| 20 #include "base/message_pump_win.h" | 21 #include "base/message_pump_win.h" |
| 21 #include "base/win/scoped_handle.h" | 22 #include "base/win/scoped_handle.h" |
| 22 #endif | 23 #endif |
| 23 | 24 |
| (...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 } | 593 } |
| 593 | 594 |
| 594 const wchar_t* const kMessageBoxTitle = L"MessageLoop Unit Test"; | 595 const wchar_t* const kMessageBoxTitle = L"MessageLoop Unit Test"; |
| 595 | 596 |
| 596 enum TaskType { | 597 enum TaskType { |
| 597 MESSAGEBOX, | 598 MESSAGEBOX, |
| 598 ENDDIALOG, | 599 ENDDIALOG, |
| 599 RECURSIVE, | 600 RECURSIVE, |
| 600 TIMEDMESSAGELOOP, | 601 TIMEDMESSAGELOOP, |
| 601 QUITMESSAGELOOP, | 602 QUITMESSAGELOOP, |
| 602 ORDERERD, | 603 ORDERED, |
| 603 PUMPS, | 604 PUMPS, |
| 604 SLEEP, | 605 SLEEP, |
| 606 RUNS, |
| 605 }; | 607 }; |
| 606 | 608 |
| 607 // Saves the order in which the tasks executed. | 609 // Saves the order in which the tasks executed. |
| 608 struct TaskItem { | 610 struct TaskItem { |
| 609 TaskItem(TaskType t, int c, bool s) | 611 TaskItem(TaskType t, int c, bool s) |
| 610 : type(t), | 612 : type(t), |
| 611 cookie(c), | 613 cookie(c), |
| 612 start(s) { | 614 start(s) { |
| 613 } | 615 } |
| 614 | 616 |
| 615 TaskType type; | 617 TaskType type; |
| 616 int cookie; | 618 int cookie; |
| 617 bool start; | 619 bool start; |
| 618 | 620 |
| 619 bool operator == (const TaskItem& other) const { | 621 bool operator == (const TaskItem& other) const { |
| 620 return type == other.type && cookie == other.cookie && start == other.start; | 622 return type == other.type && cookie == other.cookie && start == other.start; |
| 621 } | 623 } |
| 622 }; | 624 }; |
| 623 | 625 |
| 624 std::ostream& operator <<(std::ostream& os, TaskType type) { | 626 std::ostream& operator <<(std::ostream& os, TaskType type) { |
| 625 switch (type) { | 627 switch (type) { |
| 626 case MESSAGEBOX: os << "MESSAGEBOX"; break; | 628 case MESSAGEBOX: os << "MESSAGEBOX"; break; |
| 627 case ENDDIALOG: os << "ENDDIALOG"; break; | 629 case ENDDIALOG: os << "ENDDIALOG"; break; |
| 628 case RECURSIVE: os << "RECURSIVE"; break; | 630 case RECURSIVE: os << "RECURSIVE"; break; |
| 629 case TIMEDMESSAGELOOP: os << "TIMEDMESSAGELOOP"; break; | 631 case TIMEDMESSAGELOOP: os << "TIMEDMESSAGELOOP"; break; |
| 630 case QUITMESSAGELOOP: os << "QUITMESSAGELOOP"; break; | 632 case QUITMESSAGELOOP: os << "QUITMESSAGELOOP"; break; |
| 631 case ORDERERD: os << "ORDERERD"; break; | 633 case ORDERED: os << "ORDERED"; break; |
| 632 case PUMPS: os << "PUMPS"; break; | 634 case PUMPS: os << "PUMPS"; break; |
| 633 case SLEEP: os << "SLEEP"; break; | 635 case SLEEP: os << "SLEEP"; break; |
| 634 default: | 636 default: |
| 635 NOTREACHED(); | 637 NOTREACHED(); |
| 636 os << "Unknown TaskType"; | 638 os << "Unknown TaskType"; |
| 637 break; | 639 break; |
| 638 } | 640 } |
| 639 return os; | 641 return os; |
| 640 } | 642 } |
| 641 | 643 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 667 TaskItem Get(int n) { | 669 TaskItem Get(int n) { |
| 668 return task_list_[n]; | 670 return task_list_[n]; |
| 669 } | 671 } |
| 670 | 672 |
| 671 private: | 673 private: |
| 672 std::vector<TaskItem> task_list_; | 674 std::vector<TaskItem> task_list_; |
| 673 }; | 675 }; |
| 674 | 676 |
| 675 // Saves the order the tasks ran. | 677 // Saves the order the tasks ran. |
| 676 void OrderedFunc(TaskList* order, int cookie) { | 678 void OrderedFunc(TaskList* order, int cookie) { |
| 677 order->RecordStart(ORDERERD, cookie); | 679 order->RecordStart(ORDERED, cookie); |
| 678 order->RecordEnd(ORDERERD, cookie); | 680 order->RecordEnd(ORDERED, cookie); |
| 679 } | 681 } |
| 680 | 682 |
| 681 #if defined(OS_WIN) | 683 #if defined(OS_WIN) |
| 682 | 684 |
| 683 // MessageLoop implicitly start a "modal message loop". Modal dialog boxes, | 685 // MessageLoop implicitly start a "modal message loop". Modal dialog boxes, |
| 684 // common controls (like OpenFile) and StartDoc printing function can cause | 686 // common controls (like OpenFile) and StartDoc printing function can cause |
| 685 // implicit message loops. | 687 // implicit message loops. |
| 686 void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) { | 688 void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) { |
| 687 order->RecordStart(MESSAGEBOX, cookie); | 689 order->RecordStart(MESSAGEBOX, cookie); |
| 688 if (is_reentrant) | 690 if (is_reentrant) |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 840 MessageLoop::current()->Run(); | 842 MessageLoop::current()->Run(); |
| 841 | 843 |
| 842 // FIFO order. | 844 // FIFO order. |
| 843 ASSERT_EQ(16U, order.Size()); | 845 ASSERT_EQ(16U, order.Size()); |
| 844 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); | 846 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); |
| 845 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); | 847 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); |
| 846 EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true)); | 848 EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true)); |
| 847 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false)); | 849 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false)); |
| 848 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 1, true)); | 850 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 1, true)); |
| 849 EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 1, false)); | 851 EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 1, false)); |
| 850 EXPECT_EQ(order.Get(6), TaskItem(ORDERERD, 3, true)); | 852 EXPECT_EQ(order.Get(6), TaskItem(ORDERED, 3, true)); |
| 851 EXPECT_EQ(order.Get(7), TaskItem(ORDERERD, 3, false)); | 853 EXPECT_EQ(order.Get(7), TaskItem(ORDERED, 3, false)); |
| 852 EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true)); | 854 EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true)); |
| 853 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false)); | 855 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false)); |
| 854 EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 4, true)); | 856 EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 4, true)); |
| 855 EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 4, false)); | 857 EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 4, false)); |
| 856 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 1, true)); | 858 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 1, true)); |
| 857 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, false)); | 859 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, false)); |
| 858 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 2, true)); | 860 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 2, true)); |
| 859 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 2, false)); | 861 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 2, false)); |
| 860 } | 862 } |
| 861 | 863 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 | 992 |
| 991 void FuncThatPumps(TaskList* order, int cookie) { | 993 void FuncThatPumps(TaskList* order, int cookie) { |
| 992 order->RecordStart(PUMPS, cookie); | 994 order->RecordStart(PUMPS, cookie); |
| 993 { | 995 { |
| 994 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); | 996 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); |
| 995 MessageLoop::current()->RunAllPending(); | 997 MessageLoop::current()->RunAllPending(); |
| 996 } | 998 } |
| 997 order->RecordEnd(PUMPS, cookie); | 999 order->RecordEnd(PUMPS, cookie); |
| 998 } | 1000 } |
| 999 | 1001 |
| 1002 void FuncThatRuns(TaskList* order, int cookie, base::RunLoop* run_loop) { |
| 1003 order->RecordStart(RUNS, cookie); |
| 1004 { |
| 1005 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); |
| 1006 run_loop->Run(); |
| 1007 } |
| 1008 order->RecordEnd(RUNS, cookie); |
| 1009 } |
| 1010 |
| 1011 void FuncThatQuitsNow() { |
| 1012 MessageLoop::current()->QuitNow(); |
| 1013 } |
| 1014 |
| 1000 // Tests that non nestable tasks run in FIFO if there are no nested loops. | 1015 // Tests that non nestable tasks run in FIFO if there are no nested loops. |
| 1001 void RunTest_NonNestableWithNoNesting( | 1016 void RunTest_NonNestableWithNoNesting( |
| 1002 MessageLoop::Type message_loop_type) { | 1017 MessageLoop::Type message_loop_type) { |
| 1003 MessageLoop loop(message_loop_type); | 1018 MessageLoop loop(message_loop_type); |
| 1004 | 1019 |
| 1005 TaskList order; | 1020 TaskList order; |
| 1006 | 1021 |
| 1007 MessageLoop::current()->PostNonNestableTask( | 1022 MessageLoop::current()->PostNonNestableTask( |
| 1008 FROM_HERE, | 1023 FROM_HERE, |
| 1009 base::Bind(&OrderedFunc, &order, 1)); | 1024 base::Bind(&OrderedFunc, &order, 1)); |
| 1010 MessageLoop::current()->PostTask(FROM_HERE, | 1025 MessageLoop::current()->PostTask(FROM_HERE, |
| 1011 base::Bind(&OrderedFunc, &order, 2)); | 1026 base::Bind(&OrderedFunc, &order, 2)); |
| 1012 MessageLoop::current()->PostTask(FROM_HERE, | 1027 MessageLoop::current()->PostTask(FROM_HERE, |
| 1013 base::Bind(&QuitFunc, &order, 3)); | 1028 base::Bind(&QuitFunc, &order, 3)); |
| 1014 MessageLoop::current()->Run(); | 1029 MessageLoop::current()->Run(); |
| 1015 | 1030 |
| 1016 // FIFO order. | 1031 // FIFO order. |
| 1017 ASSERT_EQ(6U, order.Size()); | 1032 ASSERT_EQ(6U, order.Size()); |
| 1018 EXPECT_EQ(order.Get(0), TaskItem(ORDERERD, 1, true)); | 1033 EXPECT_EQ(order.Get(0), TaskItem(ORDERED, 1, true)); |
| 1019 EXPECT_EQ(order.Get(1), TaskItem(ORDERERD, 1, false)); | 1034 EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 1, false)); |
| 1020 EXPECT_EQ(order.Get(2), TaskItem(ORDERERD, 2, true)); | 1035 EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 2, true)); |
| 1021 EXPECT_EQ(order.Get(3), TaskItem(ORDERERD, 2, false)); | 1036 EXPECT_EQ(order.Get(3), TaskItem(ORDERED, 2, false)); |
| 1022 EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true)); | 1037 EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true)); |
| 1023 EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false)); | 1038 EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false)); |
| 1024 } | 1039 } |
| 1025 | 1040 |
| 1026 // Tests that non nestable tasks don't run when there's code in the call stack. | 1041 // Tests that non nestable tasks don't run when there's code in the call stack. |
| 1027 void RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type, | 1042 void RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type, |
| 1028 bool use_delayed) { | 1043 bool use_delayed) { |
| 1029 MessageLoop loop(message_loop_type); | 1044 MessageLoop loop(message_loop_type); |
| 1030 | 1045 |
| 1031 TaskList order; | 1046 TaskList order; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1059 MessageLoop::current()->PostNonNestableTask( | 1074 MessageLoop::current()->PostNonNestableTask( |
| 1060 FROM_HERE, | 1075 FROM_HERE, |
| 1061 base::Bind(&QuitFunc, &order, 6)); | 1076 base::Bind(&QuitFunc, &order, 6)); |
| 1062 } | 1077 } |
| 1063 | 1078 |
| 1064 MessageLoop::current()->Run(); | 1079 MessageLoop::current()->Run(); |
| 1065 | 1080 |
| 1066 // FIFO order. | 1081 // FIFO order. |
| 1067 ASSERT_EQ(12U, order.Size()); | 1082 ASSERT_EQ(12U, order.Size()); |
| 1068 EXPECT_EQ(order.Get(0), TaskItem(PUMPS, 1, true)); | 1083 EXPECT_EQ(order.Get(0), TaskItem(PUMPS, 1, true)); |
| 1069 EXPECT_EQ(order.Get(1), TaskItem(ORDERERD, 3, true)); | 1084 EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 3, true)); |
| 1070 EXPECT_EQ(order.Get(2), TaskItem(ORDERERD, 3, false)); | 1085 EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 3, false)); |
| 1071 EXPECT_EQ(order.Get(3), TaskItem(SLEEP, 4, true)); | 1086 EXPECT_EQ(order.Get(3), TaskItem(SLEEP, 4, true)); |
| 1072 EXPECT_EQ(order.Get(4), TaskItem(SLEEP, 4, false)); | 1087 EXPECT_EQ(order.Get(4), TaskItem(SLEEP, 4, false)); |
| 1073 EXPECT_EQ(order.Get(5), TaskItem(ORDERERD, 5, true)); | 1088 EXPECT_EQ(order.Get(5), TaskItem(ORDERED, 5, true)); |
| 1074 EXPECT_EQ(order.Get(6), TaskItem(ORDERERD, 5, false)); | 1089 EXPECT_EQ(order.Get(6), TaskItem(ORDERED, 5, false)); |
| 1075 EXPECT_EQ(order.Get(7), TaskItem(PUMPS, 1, false)); | 1090 EXPECT_EQ(order.Get(7), TaskItem(PUMPS, 1, false)); |
| 1076 EXPECT_EQ(order.Get(8), TaskItem(ORDERERD, 2, true)); | 1091 EXPECT_EQ(order.Get(8), TaskItem(ORDERED, 2, true)); |
| 1077 EXPECT_EQ(order.Get(9), TaskItem(ORDERERD, 2, false)); | 1092 EXPECT_EQ(order.Get(9), TaskItem(ORDERED, 2, false)); |
| 1078 EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 6, true)); | 1093 EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 6, true)); |
| 1079 EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 6, false)); | 1094 EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 6, false)); |
| 1080 } | 1095 } |
| 1081 | 1096 |
| 1097 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run. |
| 1098 void RunTest_QuitNow(MessageLoop::Type message_loop_type) { |
| 1099 MessageLoop loop(message_loop_type); |
| 1100 |
| 1101 TaskList order; |
| 1102 |
| 1103 base::RunLoop run_loop; |
| 1104 |
| 1105 MessageLoop::current()->PostTask(FROM_HERE, |
| 1106 base::Bind(&FuncThatRuns, &order, 1, base::Unretained(&run_loop))); |
| 1107 MessageLoop::current()->PostTask( |
| 1108 FROM_HERE, base::Bind(&OrderedFunc, &order, 2)); |
| 1109 MessageLoop::current()->PostTask( |
| 1110 FROM_HERE, base::Bind(&FuncThatQuitsNow)); |
| 1111 MessageLoop::current()->PostTask( |
| 1112 FROM_HERE, base::Bind(&OrderedFunc, &order, 3)); |
| 1113 MessageLoop::current()->PostTask( |
| 1114 FROM_HERE, base::Bind(&FuncThatQuitsNow)); |
| 1115 MessageLoop::current()->PostTask( |
| 1116 FROM_HERE, base::Bind(&OrderedFunc, &order, 4)); // never runs |
| 1117 |
| 1118 MessageLoop::current()->Run(); |
| 1119 |
| 1120 ASSERT_EQ(6U, order.Size()); |
| 1121 int task_index = 0; |
| 1122 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true)); |
| 1123 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true)); |
| 1124 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false)); |
| 1125 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false)); |
| 1126 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true)); |
| 1127 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false)); |
| 1128 EXPECT_EQ(static_cast<size_t>(task_index), order.Size()); |
| 1129 } |
| 1130 |
| 1131 // Tests RunLoopQuit works before RunWithID. |
| 1132 void RunTest_RunLoopQuitOrderBefore(MessageLoop::Type message_loop_type) { |
| 1133 MessageLoop loop(message_loop_type); |
| 1134 |
| 1135 TaskList order; |
| 1136 |
| 1137 base::RunLoop run_loop; |
| 1138 |
| 1139 run_loop.Quit(); |
| 1140 |
| 1141 MessageLoop::current()->PostTask( |
| 1142 FROM_HERE, base::Bind(&OrderedFunc, &order, 1)); // never runs |
| 1143 MessageLoop::current()->PostTask( |
| 1144 FROM_HERE, base::Bind(&FuncThatQuitsNow)); // never runs |
| 1145 |
| 1146 run_loop.Run(); |
| 1147 |
| 1148 ASSERT_EQ(0U, order.Size()); |
| 1149 } |
| 1150 |
| 1151 // Tests RunLoopQuit works during RunWithID. |
| 1152 void RunTest_RunLoopQuitOrderDuring(MessageLoop::Type message_loop_type) { |
| 1153 MessageLoop loop(message_loop_type); |
| 1154 |
| 1155 TaskList order; |
| 1156 |
| 1157 base::RunLoop run_loop; |
| 1158 |
| 1159 MessageLoop::current()->PostTask( |
| 1160 FROM_HERE, base::Bind(&OrderedFunc, &order, 1)); |
| 1161 MessageLoop::current()->PostTask( |
| 1162 FROM_HERE, run_loop.QuitClosure()); |
| 1163 MessageLoop::current()->PostTask( |
| 1164 FROM_HERE, base::Bind(&OrderedFunc, &order, 2)); // never runs |
| 1165 MessageLoop::current()->PostTask( |
| 1166 FROM_HERE, base::Bind(&FuncThatQuitsNow)); // never runs |
| 1167 |
| 1168 run_loop.Run(); |
| 1169 |
| 1170 ASSERT_EQ(2U, order.Size()); |
| 1171 int task_index = 0; |
| 1172 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, true)); |
| 1173 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, false)); |
| 1174 EXPECT_EQ(static_cast<size_t>(task_index), order.Size()); |
| 1175 } |
| 1176 |
| 1177 // Tests RunLoopQuit works after RunWithID. |
| 1178 void RunTest_RunLoopQuitOrderAfter(MessageLoop::Type message_loop_type) { |
| 1179 MessageLoop loop(message_loop_type); |
| 1180 |
| 1181 TaskList order; |
| 1182 |
| 1183 base::RunLoop run_loop; |
| 1184 |
| 1185 MessageLoop::current()->PostTask(FROM_HERE, |
| 1186 base::Bind(&FuncThatRuns, &order, 1, base::Unretained(&run_loop))); |
| 1187 MessageLoop::current()->PostTask( |
| 1188 FROM_HERE, base::Bind(&OrderedFunc, &order, 2)); |
| 1189 MessageLoop::current()->PostTask( |
| 1190 FROM_HERE, base::Bind(&FuncThatQuitsNow)); |
| 1191 MessageLoop::current()->PostTask( |
| 1192 FROM_HERE, base::Bind(&OrderedFunc, &order, 3)); |
| 1193 MessageLoop::current()->PostTask( |
| 1194 FROM_HERE, run_loop.QuitClosure()); // has no affect |
| 1195 MessageLoop::current()->PostTask( |
| 1196 FROM_HERE, base::Bind(&OrderedFunc, &order, 4)); |
| 1197 MessageLoop::current()->PostTask( |
| 1198 FROM_HERE, base::Bind(&FuncThatQuitsNow)); |
| 1199 |
| 1200 base::RunLoop outer_run_loop; |
| 1201 outer_run_loop.Run(); |
| 1202 |
| 1203 ASSERT_EQ(8U, order.Size()); |
| 1204 int task_index = 0; |
| 1205 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true)); |
| 1206 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true)); |
| 1207 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false)); |
| 1208 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false)); |
| 1209 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true)); |
| 1210 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false)); |
| 1211 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, true)); |
| 1212 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, false)); |
| 1213 EXPECT_EQ(static_cast<size_t>(task_index), order.Size()); |
| 1214 } |
| 1215 |
| 1216 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run. |
| 1217 void RunTest_RunLoopQuitTop(MessageLoop::Type message_loop_type) { |
| 1218 MessageLoop loop(message_loop_type); |
| 1219 |
| 1220 TaskList order; |
| 1221 |
| 1222 base::RunLoop outer_run_loop; |
| 1223 base::RunLoop nested_run_loop; |
| 1224 |
| 1225 MessageLoop::current()->PostTask(FROM_HERE, |
| 1226 base::Bind(&FuncThatRuns, &order, 1, base::Unretained(&nested_run_loop))); |
| 1227 MessageLoop::current()->PostTask( |
| 1228 FROM_HERE, outer_run_loop.QuitClosure()); |
| 1229 MessageLoop::current()->PostTask( |
| 1230 FROM_HERE, base::Bind(&OrderedFunc, &order, 2)); |
| 1231 MessageLoop::current()->PostTask( |
| 1232 FROM_HERE, nested_run_loop.QuitClosure()); |
| 1233 |
| 1234 outer_run_loop.Run(); |
| 1235 |
| 1236 ASSERT_EQ(4U, order.Size()); |
| 1237 int task_index = 0; |
| 1238 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true)); |
| 1239 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true)); |
| 1240 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false)); |
| 1241 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false)); |
| 1242 EXPECT_EQ(static_cast<size_t>(task_index), order.Size()); |
| 1243 } |
| 1244 |
| 1245 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run. |
| 1246 void RunTest_RunLoopQuitNested(MessageLoop::Type message_loop_type) { |
| 1247 MessageLoop loop(message_loop_type); |
| 1248 |
| 1249 TaskList order; |
| 1250 |
| 1251 base::RunLoop outer_run_loop; |
| 1252 base::RunLoop nested_run_loop; |
| 1253 |
| 1254 MessageLoop::current()->PostTask(FROM_HERE, |
| 1255 base::Bind(&FuncThatRuns, &order, 1, base::Unretained(&nested_run_loop))); |
| 1256 MessageLoop::current()->PostTask( |
| 1257 FROM_HERE, nested_run_loop.QuitClosure()); |
| 1258 MessageLoop::current()->PostTask( |
| 1259 FROM_HERE, base::Bind(&OrderedFunc, &order, 2)); |
| 1260 MessageLoop::current()->PostTask( |
| 1261 FROM_HERE, outer_run_loop.QuitClosure()); |
| 1262 |
| 1263 outer_run_loop.Run(); |
| 1264 |
| 1265 ASSERT_EQ(4U, order.Size()); |
| 1266 int task_index = 0; |
| 1267 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true)); |
| 1268 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false)); |
| 1269 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true)); |
| 1270 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false)); |
| 1271 EXPECT_EQ(static_cast<size_t>(task_index), order.Size()); |
| 1272 } |
| 1273 |
| 1274 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run. |
| 1275 void RunTest_RunLoopQuitBogus(MessageLoop::Type message_loop_type) { |
| 1276 MessageLoop loop(message_loop_type); |
| 1277 |
| 1278 TaskList order; |
| 1279 |
| 1280 base::RunLoop outer_run_loop; |
| 1281 base::RunLoop nested_run_loop; |
| 1282 base::RunLoop bogus_run_loop; |
| 1283 |
| 1284 MessageLoop::current()->PostTask(FROM_HERE, |
| 1285 base::Bind(&FuncThatRuns, &order, 1, base::Unretained(&nested_run_loop))); |
| 1286 MessageLoop::current()->PostTask( |
| 1287 FROM_HERE, bogus_run_loop.QuitClosure()); |
| 1288 MessageLoop::current()->PostTask( |
| 1289 FROM_HERE, base::Bind(&OrderedFunc, &order, 2)); |
| 1290 MessageLoop::current()->PostTask( |
| 1291 FROM_HERE, outer_run_loop.QuitClosure()); |
| 1292 MessageLoop::current()->PostTask( |
| 1293 FROM_HERE, nested_run_loop.QuitClosure()); |
| 1294 |
| 1295 outer_run_loop.Run(); |
| 1296 |
| 1297 ASSERT_EQ(4U, order.Size()); |
| 1298 int task_index = 0; |
| 1299 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true)); |
| 1300 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true)); |
| 1301 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false)); |
| 1302 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false)); |
| 1303 EXPECT_EQ(static_cast<size_t>(task_index), order.Size()); |
| 1304 } |
| 1305 |
| 1306 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run. |
| 1307 void RunTest_RunLoopQuitDeep(MessageLoop::Type message_loop_type) { |
| 1308 MessageLoop loop(message_loop_type); |
| 1309 |
| 1310 TaskList order; |
| 1311 |
| 1312 base::RunLoop outer_run_loop; |
| 1313 base::RunLoop nested_loop1; |
| 1314 base::RunLoop nested_loop2; |
| 1315 base::RunLoop nested_loop3; |
| 1316 base::RunLoop nested_loop4; |
| 1317 |
| 1318 MessageLoop::current()->PostTask(FROM_HERE, |
| 1319 base::Bind(&FuncThatRuns, &order, 1, base::Unretained(&nested_loop1))); |
| 1320 MessageLoop::current()->PostTask(FROM_HERE, |
| 1321 base::Bind(&FuncThatRuns, &order, 2, base::Unretained(&nested_loop2))); |
| 1322 MessageLoop::current()->PostTask(FROM_HERE, |
| 1323 base::Bind(&FuncThatRuns, &order, 3, base::Unretained(&nested_loop3))); |
| 1324 MessageLoop::current()->PostTask(FROM_HERE, |
| 1325 base::Bind(&FuncThatRuns, &order, 4, base::Unretained(&nested_loop4))); |
| 1326 MessageLoop::current()->PostTask( |
| 1327 FROM_HERE, base::Bind(&OrderedFunc, &order, 5)); |
| 1328 MessageLoop::current()->PostTask( |
| 1329 FROM_HERE, outer_run_loop.QuitClosure()); |
| 1330 MessageLoop::current()->PostTask( |
| 1331 FROM_HERE, base::Bind(&OrderedFunc, &order, 6)); |
| 1332 MessageLoop::current()->PostTask( |
| 1333 FROM_HERE, nested_loop1.QuitClosure()); |
| 1334 MessageLoop::current()->PostTask( |
| 1335 FROM_HERE, base::Bind(&OrderedFunc, &order, 7)); |
| 1336 MessageLoop::current()->PostTask( |
| 1337 FROM_HERE, nested_loop2.QuitClosure()); |
| 1338 MessageLoop::current()->PostTask( |
| 1339 FROM_HERE, base::Bind(&OrderedFunc, &order, 8)); |
| 1340 MessageLoop::current()->PostTask( |
| 1341 FROM_HERE, nested_loop3.QuitClosure()); |
| 1342 MessageLoop::current()->PostTask( |
| 1343 FROM_HERE, base::Bind(&OrderedFunc, &order, 9)); |
| 1344 MessageLoop::current()->PostTask( |
| 1345 FROM_HERE, nested_loop4.QuitClosure()); |
| 1346 MessageLoop::current()->PostTask( |
| 1347 FROM_HERE, base::Bind(&OrderedFunc, &order, 10)); |
| 1348 |
| 1349 outer_run_loop.Run(); |
| 1350 |
| 1351 ASSERT_EQ(18U, order.Size()); |
| 1352 int task_index = 0; |
| 1353 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true)); |
| 1354 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, true)); |
| 1355 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, true)); |
| 1356 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, true)); |
| 1357 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, true)); |
| 1358 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, false)); |
| 1359 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, true)); |
| 1360 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, false)); |
| 1361 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, true)); |
| 1362 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, false)); |
| 1363 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, true)); |
| 1364 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, false)); |
| 1365 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, true)); |
| 1366 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, false)); |
| 1367 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, false)); |
| 1368 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, false)); |
| 1369 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, false)); |
| 1370 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false)); |
| 1371 EXPECT_EQ(static_cast<size_t>(task_index), order.Size()); |
| 1372 } |
| 1373 |
| 1082 #if defined(OS_WIN) | 1374 #if defined(OS_WIN) |
| 1083 | 1375 |
| 1084 class DispatcherImpl : public MessageLoopForUI::Dispatcher { | 1376 class DispatcherImpl : public MessageLoopForUI::Dispatcher { |
| 1085 public: | 1377 public: |
| 1086 DispatcherImpl() : dispatch_count_(0) {} | 1378 DispatcherImpl() : dispatch_count_(0) {} |
| 1087 | 1379 |
| 1088 virtual bool Dispatch(const base::NativeEvent& msg) OVERRIDE { | 1380 virtual bool Dispatch(const base::NativeEvent& msg) OVERRIDE { |
| 1089 ::TranslateMessage(&msg); | 1381 ::TranslateMessage(&msg); |
| 1090 ::DispatchMessage(&msg); | 1382 ::DispatchMessage(&msg); |
| 1091 // Do not count WM_TIMER since it is not what we post and it will cause | 1383 // Do not count WM_TIMER since it is not what we post and it will cause |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1105 } | 1397 } |
| 1106 | 1398 |
| 1107 void RunTest_Dispatcher(MessageLoop::Type message_loop_type) { | 1399 void RunTest_Dispatcher(MessageLoop::Type message_loop_type) { |
| 1108 MessageLoop loop(message_loop_type); | 1400 MessageLoop loop(message_loop_type); |
| 1109 | 1401 |
| 1110 MessageLoop::current()->PostDelayedTask( | 1402 MessageLoop::current()->PostDelayedTask( |
| 1111 FROM_HERE, | 1403 FROM_HERE, |
| 1112 base::Bind(&MouseDownUp), | 1404 base::Bind(&MouseDownUp), |
| 1113 TimeDelta::FromMilliseconds(100)); | 1405 TimeDelta::FromMilliseconds(100)); |
| 1114 DispatcherImpl dispatcher; | 1406 DispatcherImpl dispatcher; |
| 1115 MessageLoopForUI::current()->RunWithDispatcher(&dispatcher); | 1407 base::RunLoop run_loop(&dispatcher); |
| 1408 run_loop.Run(); |
| 1116 ASSERT_EQ(2, dispatcher.dispatch_count_); | 1409 ASSERT_EQ(2, dispatcher.dispatch_count_); |
| 1117 } | 1410 } |
| 1118 | 1411 |
| 1119 LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) { | 1412 LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) { |
| 1120 if (code == base::MessagePumpForUI::kMessageFilterCode) { | 1413 if (code == base::MessagePumpForUI::kMessageFilterCode) { |
| 1121 MSG* msg = reinterpret_cast<MSG*>(lparam); | 1414 MSG* msg = reinterpret_cast<MSG*>(lparam); |
| 1122 if (msg->message == WM_LBUTTONDOWN) | 1415 if (msg->message == WM_LBUTTONDOWN) |
| 1123 return TRUE; | 1416 return TRUE; |
| 1124 } | 1417 } |
| 1125 return FALSE; | 1418 return FALSE; |
| 1126 } | 1419 } |
| 1127 | 1420 |
| 1128 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) { | 1421 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) { |
| 1129 MessageLoop loop(message_loop_type); | 1422 MessageLoop loop(message_loop_type); |
| 1130 | 1423 |
| 1131 MessageLoop::current()->PostDelayedTask( | 1424 MessageLoop::current()->PostDelayedTask( |
| 1132 FROM_HERE, | 1425 FROM_HERE, |
| 1133 base::Bind(&MouseDownUp), | 1426 base::Bind(&MouseDownUp), |
| 1134 TimeDelta::FromMilliseconds(100)); | 1427 TimeDelta::FromMilliseconds(100)); |
| 1135 HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER, | 1428 HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER, |
| 1136 MsgFilterProc, | 1429 MsgFilterProc, |
| 1137 NULL, | 1430 NULL, |
| 1138 GetCurrentThreadId()); | 1431 GetCurrentThreadId()); |
| 1139 DispatcherImpl dispatcher; | 1432 DispatcherImpl dispatcher; |
| 1140 MessageLoopForUI::current()->RunWithDispatcher(&dispatcher); | 1433 base::RunLoop run_loop(&dispatcher); |
| 1434 run_loop.Run(); |
| 1141 ASSERT_EQ(1, dispatcher.dispatch_count_); | 1435 ASSERT_EQ(1, dispatcher.dispatch_count_); |
| 1142 UnhookWindowsHookEx(msg_hook); | 1436 UnhookWindowsHookEx(msg_hook); |
| 1143 } | 1437 } |
| 1144 | 1438 |
| 1145 class TestIOHandler : public MessageLoopForIO::IOHandler { | 1439 class TestIOHandler : public MessageLoopForIO::IOHandler { |
| 1146 public: | 1440 public: |
| 1147 TestIOHandler(const wchar_t* name, HANDLE signal, bool wait); | 1441 TestIOHandler(const wchar_t* name, HANDLE signal, bool wait); |
| 1148 | 1442 |
| 1149 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, | 1443 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, |
| 1150 DWORD bytes_transfered, DWORD error); | 1444 DWORD bytes_transfered, DWORD error); |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, false); | 1721 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, false); |
| 1428 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, false); | 1722 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, false); |
| 1429 } | 1723 } |
| 1430 | 1724 |
| 1431 TEST(MessageLoopTest, NonNestableDelayedInNestedLoop) { | 1725 TEST(MessageLoopTest, NonNestableDelayedInNestedLoop) { |
| 1432 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, true); | 1726 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, true); |
| 1433 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, true); | 1727 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, true); |
| 1434 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, true); | 1728 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, true); |
| 1435 } | 1729 } |
| 1436 | 1730 |
| 1731 TEST(MessageLoopTest, QuitNow) { |
| 1732 RunTest_QuitNow(MessageLoop::TYPE_DEFAULT); |
| 1733 RunTest_QuitNow(MessageLoop::TYPE_UI); |
| 1734 RunTest_QuitNow(MessageLoop::TYPE_IO); |
| 1735 } |
| 1736 |
| 1737 TEST(MessageLoopTest, RunLoopQuitTop) { |
| 1738 RunTest_RunLoopQuitTop(MessageLoop::TYPE_DEFAULT); |
| 1739 RunTest_RunLoopQuitTop(MessageLoop::TYPE_UI); |
| 1740 RunTest_RunLoopQuitTop(MessageLoop::TYPE_IO); |
| 1741 } |
| 1742 |
| 1743 TEST(MessageLoopTest, RunLoopQuitNested) { |
| 1744 RunTest_RunLoopQuitNested(MessageLoop::TYPE_DEFAULT); |
| 1745 RunTest_RunLoopQuitNested(MessageLoop::TYPE_UI); |
| 1746 RunTest_RunLoopQuitNested(MessageLoop::TYPE_IO); |
| 1747 } |
| 1748 |
| 1749 TEST(MessageLoopTest, RunLoopQuitBogus) { |
| 1750 RunTest_RunLoopQuitBogus(MessageLoop::TYPE_DEFAULT); |
| 1751 RunTest_RunLoopQuitBogus(MessageLoop::TYPE_UI); |
| 1752 RunTest_RunLoopQuitBogus(MessageLoop::TYPE_IO); |
| 1753 } |
| 1754 |
| 1755 TEST(MessageLoopTest, RunLoopQuitDeep) { |
| 1756 RunTest_RunLoopQuitDeep(MessageLoop::TYPE_DEFAULT); |
| 1757 RunTest_RunLoopQuitDeep(MessageLoop::TYPE_UI); |
| 1758 RunTest_RunLoopQuitDeep(MessageLoop::TYPE_IO); |
| 1759 } |
| 1760 |
| 1761 TEST(MessageLoopTest, RunLoopQuitOrderBefore) { |
| 1762 RunTest_RunLoopQuitOrderBefore(MessageLoop::TYPE_DEFAULT); |
| 1763 RunTest_RunLoopQuitOrderBefore(MessageLoop::TYPE_UI); |
| 1764 RunTest_RunLoopQuitOrderBefore(MessageLoop::TYPE_IO); |
| 1765 } |
| 1766 |
| 1767 TEST(MessageLoopTest, RunLoopQuitOrderDuring) { |
| 1768 RunTest_RunLoopQuitOrderDuring(MessageLoop::TYPE_DEFAULT); |
| 1769 RunTest_RunLoopQuitOrderDuring(MessageLoop::TYPE_UI); |
| 1770 RunTest_RunLoopQuitOrderDuring(MessageLoop::TYPE_IO); |
| 1771 } |
| 1772 |
| 1773 TEST(MessageLoopTest, RunLoopQuitOrderAfter) { |
| 1774 RunTest_RunLoopQuitOrderAfter(MessageLoop::TYPE_DEFAULT); |
| 1775 RunTest_RunLoopQuitOrderAfter(MessageLoop::TYPE_UI); |
| 1776 RunTest_RunLoopQuitOrderAfter(MessageLoop::TYPE_IO); |
| 1777 } |
| 1778 |
| 1437 void PostNTasksThenQuit(int posts_remaining) { | 1779 void PostNTasksThenQuit(int posts_remaining) { |
| 1438 if (posts_remaining > 1) { | 1780 if (posts_remaining > 1) { |
| 1439 MessageLoop::current()->PostTask( | 1781 MessageLoop::current()->PostTask( |
| 1440 FROM_HERE, | 1782 FROM_HERE, |
| 1441 base::Bind(&PostNTasksThenQuit, posts_remaining - 1)); | 1783 base::Bind(&PostNTasksThenQuit, posts_remaining - 1)); |
| 1442 } else { | 1784 } else { |
| 1443 MessageLoop::current()->Quit(); | 1785 MessageLoop::current()->Quit(); |
| 1444 } | 1786 } |
| 1445 } | 1787 } |
| 1446 | 1788 |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1705 // Post quit task; | 2047 // Post quit task; |
| 1706 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 2048 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
| 1707 &MessageLoop::Quit, base::Unretained(MessageLoop::current()))); | 2049 &MessageLoop::Quit, base::Unretained(MessageLoop::current()))); |
| 1708 | 2050 |
| 1709 // Now kick things off | 2051 // Now kick things off |
| 1710 MessageLoop::current()->Run(); | 2052 MessageLoop::current()->Run(); |
| 1711 | 2053 |
| 1712 EXPECT_EQ(foo->test_count(), 1); | 2054 EXPECT_EQ(foo->test_count(), 1); |
| 1713 EXPECT_EQ(foo->result(), "a"); | 2055 EXPECT_EQ(foo->result(), "a"); |
| 1714 } | 2056 } |
| OLD | NEW |