registry.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. #include <unordered_map>
  2. #include <unordered_set>
  3. #include <functional>
  4. #include <type_traits>
  5. #include <gtest/gtest.h>
  6. #include <entt/entity/entt_traits.hpp>
  7. #include <entt/entity/registry.hpp>
  8. struct ComponentListener {
  9. void incr(entt::DefaultRegistry &, entt::DefaultRegistry::entity_type entity) {
  10. last = entity;
  11. ++counter;
  12. }
  13. void decr(entt::DefaultRegistry &, entt::DefaultRegistry::entity_type entity) {
  14. last = entity;
  15. --counter;
  16. }
  17. entt::DefaultRegistry::entity_type last;
  18. int counter{0};
  19. };
  20. TEST(DefaultRegistry, Functionalities) {
  21. entt::DefaultRegistry registry;
  22. ASSERT_EQ(registry.size(), entt::DefaultRegistry::size_type{0});
  23. ASSERT_NO_THROW(registry.reserve(42));
  24. ASSERT_NO_THROW(registry.reserve<int>(8));
  25. ASSERT_NO_THROW(registry.reserve<char>(8));
  26. ASSERT_TRUE(registry.empty());
  27. ASSERT_EQ(registry.capacity(), entt::DefaultRegistry::size_type{0});
  28. ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{0});
  29. ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{0});
  30. ASSERT_TRUE(registry.empty<int>());
  31. ASSERT_TRUE(registry.empty<char>());
  32. const auto e0 = registry.create();
  33. const auto e1 = registry.create();
  34. registry.assign<int>(e1);
  35. registry.assign<char>(e1);
  36. ASSERT_TRUE(registry.has<>(e0));
  37. ASSERT_TRUE(registry.has<>(e1));
  38. ASSERT_EQ(registry.capacity(), entt::DefaultRegistry::size_type{2});
  39. ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{1});
  40. ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{1});
  41. ASSERT_FALSE(registry.empty<int>());
  42. ASSERT_FALSE(registry.empty<char>());
  43. ASSERT_NE(e0, e1);
  44. ASSERT_FALSE(registry.has<int>(e0));
  45. ASSERT_TRUE(registry.has<int>(e1));
  46. ASSERT_FALSE(registry.has<char>(e0));
  47. ASSERT_TRUE(registry.has<char>(e1));
  48. ASSERT_FALSE((registry.has<int, char>(e0)));
  49. ASSERT_TRUE((registry.has<int, char>(e1)));
  50. ASSERT_EQ(registry.assign<int>(e0, 42), 42);
  51. ASSERT_EQ(registry.assign<char>(e0, 'c'), 'c');
  52. ASSERT_NO_THROW(registry.remove<int>(e1));
  53. ASSERT_NO_THROW(registry.remove<char>(e1));
  54. ASSERT_TRUE(registry.has<int>(e0));
  55. ASSERT_FALSE(registry.has<int>(e1));
  56. ASSERT_TRUE(registry.has<char>(e0));
  57. ASSERT_FALSE(registry.has<char>(e1));
  58. ASSERT_TRUE((registry.has<int, char>(e0)));
  59. ASSERT_FALSE((registry.has<int, char>(e1)));
  60. const auto e2 = registry.create();
  61. registry.accommodate<int>(e2, registry.get<int>(e0));
  62. registry.accommodate<char>(e2, registry.get<char>(e0));
  63. ASSERT_TRUE(registry.has<int>(e2));
  64. ASSERT_TRUE(registry.has<char>(e2));
  65. ASSERT_EQ(registry.get<int>(e0), 42);
  66. ASSERT_EQ(registry.get<char>(e0), 'c');
  67. ASSERT_EQ(std::get<0>(registry.get<int, char>(e0)), 42);
  68. ASSERT_EQ(std::get<1>(static_cast<const entt::DefaultRegistry &>(registry).get<int, char>(e0)), 'c');
  69. ASSERT_EQ(registry.get<int>(e0), registry.get<int>(e2));
  70. ASSERT_EQ(registry.get<char>(e0), registry.get<char>(e2));
  71. ASSERT_NE(&registry.get<int>(e0), &registry.get<int>(e2));
  72. ASSERT_NE(&registry.get<char>(e0), &registry.get<char>(e2));
  73. ASSERT_NO_THROW(registry.replace<int>(e0, 0));
  74. ASSERT_EQ(registry.get<int>(e0), 0);
  75. ASSERT_NO_THROW(registry.accommodate<int>(e0, 1));
  76. ASSERT_NO_THROW(registry.accommodate<int>(e1, 1));
  77. ASSERT_EQ(static_cast<const entt::DefaultRegistry &>(registry).get<int>(e0), 1);
  78. ASSERT_EQ(static_cast<const entt::DefaultRegistry &>(registry).get<int>(e1), 1);
  79. ASSERT_EQ(registry.size(), entt::DefaultRegistry::size_type{3});
  80. ASSERT_FALSE(registry.empty());
  81. ASSERT_EQ(registry.version(e2), entt::DefaultRegistry::version_type{0});
  82. ASSERT_EQ(registry.current(e2), entt::DefaultRegistry::version_type{0});
  83. ASSERT_EQ(registry.capacity(), entt::DefaultRegistry::size_type{3});
  84. ASSERT_NO_THROW(registry.destroy(e2));
  85. ASSERT_EQ(registry.capacity(), entt::DefaultRegistry::size_type{3});
  86. ASSERT_EQ(registry.version(e2), entt::DefaultRegistry::version_type{0});
  87. ASSERT_EQ(registry.current(e2), entt::DefaultRegistry::version_type{1});
  88. ASSERT_TRUE(registry.valid(e0));
  89. ASSERT_TRUE(registry.fast(e0));
  90. ASSERT_TRUE(registry.valid(e1));
  91. ASSERT_TRUE(registry.fast(e1));
  92. ASSERT_FALSE(registry.valid(e2));
  93. ASSERT_FALSE(registry.fast(e2));
  94. ASSERT_EQ(registry.size(), entt::DefaultRegistry::size_type{2});
  95. ASSERT_FALSE(registry.empty());
  96. ASSERT_NO_THROW(registry.reset());
  97. ASSERT_EQ(registry.size(), entt::DefaultRegistry::size_type{0});
  98. ASSERT_TRUE(registry.empty());
  99. const auto e3 = registry.create();
  100. registry.assign<int>(e3);
  101. registry.assign<char>(e3);
  102. ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{1});
  103. ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{1});
  104. ASSERT_FALSE(registry.empty<int>());
  105. ASSERT_FALSE(registry.empty<char>());
  106. ASSERT_NO_THROW(registry.reset<int>());
  107. ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{0});
  108. ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{1});
  109. ASSERT_TRUE(registry.empty<int>());
  110. ASSERT_FALSE(registry.empty<char>());
  111. ASSERT_NO_THROW(registry.reset());
  112. ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{0});
  113. ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{0});
  114. ASSERT_TRUE(registry.empty<int>());
  115. ASSERT_TRUE(registry.empty<char>());
  116. const auto e4 = registry.create();
  117. const auto e5 = registry.create();
  118. registry.assign<int>(e4);
  119. ASSERT_NO_THROW(registry.reset<int>(e4));
  120. ASSERT_NO_THROW(registry.reset<int>(e5));
  121. ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{0});
  122. ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{0});
  123. ASSERT_TRUE(registry.empty<int>());
  124. }
  125. TEST(DefaultRegistry, CreateDestroyCornerCase) {
  126. entt::DefaultRegistry registry;
  127. const auto e0 = registry.create();
  128. const auto e1 = registry.create();
  129. registry.destroy(e0);
  130. registry.destroy(e1);
  131. registry.each([](auto) { FAIL(); });
  132. ASSERT_EQ(registry.current(e0), entt::DefaultRegistry::version_type{1});
  133. ASSERT_EQ(registry.current(e1), entt::DefaultRegistry::version_type{1});
  134. }
  135. TEST(DefaultRegistry, VersionOverflow) {
  136. entt::DefaultRegistry registry;
  137. const auto entity = registry.create();
  138. registry.destroy(entity);
  139. ASSERT_EQ(registry.version(entity), entt::DefaultRegistry::version_type{});
  140. for(auto i = entt::entt_traits<entt::DefaultRegistry::entity_type>::version_mask; i; --i) {
  141. ASSERT_NE(registry.current(entity), registry.version(entity));
  142. registry.destroy(registry.create());
  143. }
  144. ASSERT_EQ(registry.current(entity), registry.version(entity));
  145. }
  146. TEST(DefaultRegistry, Each) {
  147. entt::DefaultRegistry registry;
  148. entt::DefaultRegistry::size_type tot;
  149. entt::DefaultRegistry::size_type match;
  150. registry.create();
  151. registry.assign<int>(registry.create());
  152. registry.create();
  153. registry.assign<int>(registry.create());
  154. registry.create();
  155. tot = 0u;
  156. match = 0u;
  157. registry.each([&](auto entity) {
  158. if(registry.has<int>(entity)) { ++match; }
  159. registry.create();
  160. ++tot;
  161. });
  162. ASSERT_EQ(tot, 5u);
  163. ASSERT_EQ(match, 2u);
  164. tot = 0u;
  165. match = 0u;
  166. registry.each([&](auto entity) {
  167. if(registry.has<int>(entity)) {
  168. registry.destroy(entity);
  169. ++match;
  170. }
  171. ++tot;
  172. });
  173. ASSERT_EQ(tot, 10u);
  174. ASSERT_EQ(match, 2u);
  175. tot = 0u;
  176. match = 0u;
  177. registry.each([&](auto entity) {
  178. if(registry.has<int>(entity)) { ++match; }
  179. registry.destroy(entity);
  180. ++tot;
  181. });
  182. ASSERT_EQ(tot, 8u);
  183. ASSERT_EQ(match, 0u);
  184. registry.each([&](auto) { FAIL(); });
  185. }
  186. TEST(DefaultRegistry, Orphans) {
  187. entt::DefaultRegistry registry;
  188. entt::DefaultRegistry::size_type tot{};
  189. registry.assign<int>(registry.create());
  190. registry.create();
  191. registry.assign<int>(registry.create());
  192. registry.create();
  193. registry.assign<double>(entt::tag_type_t{}, registry.create());
  194. registry.orphans([&](auto) { ++tot; });
  195. ASSERT_EQ(tot, 2u);
  196. tot = 0u;
  197. registry.each([&](auto entity) { registry.reset<int>(entity); });
  198. registry.orphans([&](auto) { ++tot; });
  199. ASSERT_EQ(tot, 4u);
  200. registry.reset();
  201. tot = 0u;
  202. registry.orphans([&](auto) { ++tot; });
  203. ASSERT_EQ(tot, 0u);
  204. }
  205. TEST(DefaultRegistry, Types) {
  206. entt::DefaultRegistry registry;
  207. ASSERT_EQ(registry.type<int>(entt::tag_type_t{}), registry.type<int>(entt::tag_type_t{}));
  208. ASSERT_EQ(registry.type<int>(), registry.type<int>());
  209. ASSERT_NE(registry.type<int>(entt::tag_type_t{}), registry.type<double>(entt::tag_type_t{}));
  210. ASSERT_NE(registry.type<int>(), registry.type<double>(entt::tag_type_t{}));
  211. }
  212. TEST(DefaultRegistry, CreateDestroyEntities) {
  213. entt::DefaultRegistry registry;
  214. entt::DefaultRegistry::entity_type pre{}, post{};
  215. for(int i = 0; i < 10; ++i) {
  216. const auto entity = registry.create();
  217. registry.assign<double>(entity);
  218. }
  219. registry.reset();
  220. for(int i = 0; i < 7; ++i) {
  221. const auto entity = registry.create();
  222. registry.assign<int>(entity);
  223. if(i == 3) { pre = entity; }
  224. }
  225. registry.reset();
  226. for(int i = 0; i < 5; ++i) {
  227. const auto entity = registry.create();
  228. if(i == 3) { post = entity; }
  229. }
  230. ASSERT_FALSE(registry.valid(pre));
  231. ASSERT_TRUE(registry.valid(post));
  232. ASSERT_NE(registry.version(pre), registry.version(post));
  233. ASSERT_EQ(registry.version(pre) + 1, registry.version(post));
  234. ASSERT_EQ(registry.current(pre), registry.current(post));
  235. }
  236. TEST(DefaultRegistry, AttachSetRemoveTags) {
  237. entt::DefaultRegistry registry;
  238. const auto &cregistry = registry;
  239. ASSERT_FALSE(registry.has<int>());
  240. const auto entity = registry.create();
  241. registry.assign<int>(entt::tag_type_t{}, entity, 42);
  242. ASSERT_TRUE(registry.has<int>());
  243. ASSERT_EQ(registry.get<int>(), 42);
  244. ASSERT_EQ(cregistry.get<int>(), 42);
  245. ASSERT_EQ(registry.attachee<int>(), entity);
  246. registry.replace<int>(entt::tag_type_t{}, 3);
  247. ASSERT_TRUE(registry.has<int>());
  248. ASSERT_EQ(registry.get<int>(), 3);
  249. ASSERT_EQ(cregistry.get<int>(), 3);
  250. ASSERT_EQ(registry.attachee<int>(), entity);
  251. const auto other = registry.create();
  252. registry.move<int>(other);
  253. ASSERT_TRUE(registry.has<int>());
  254. ASSERT_EQ(registry.get<int>(), 3);
  255. ASSERT_EQ(cregistry.get<int>(), 3);
  256. ASSERT_EQ(registry.attachee<int>(), other);
  257. registry.remove<int>();
  258. ASSERT_FALSE(registry.has<int>());
  259. registry.assign<int>(entt::tag_type_t{}, entity, 42);
  260. registry.destroy(entity);
  261. ASSERT_FALSE(registry.has<int>());
  262. }
  263. TEST(DefaultRegistry, StandardViews) {
  264. entt::DefaultRegistry registry;
  265. auto mview = registry.view<int, char>();
  266. auto iview = registry.view<int>();
  267. auto cview = registry.view<char>();
  268. const auto e0 = registry.create();
  269. registry.assign<int>(e0, 0);
  270. registry.assign<char>(e0, 'c');
  271. const auto e1 = registry.create();
  272. registry.assign<int>(e1, 0);
  273. const auto e2 = registry.create();
  274. registry.assign<int>(e2, 0);
  275. registry.assign<char>(e2, 'c');
  276. ASSERT_EQ(iview.size(), decltype(iview)::size_type{3});
  277. ASSERT_EQ(cview.size(), decltype(cview)::size_type{2});
  278. decltype(mview)::size_type cnt{0};
  279. mview.each([&cnt](auto...) { ++cnt; });
  280. ASSERT_EQ(cnt, decltype(mview)::size_type{2});
  281. }
  282. TEST(DefaultRegistry, PersistentViews) {
  283. entt::DefaultRegistry registry;
  284. auto view = registry.persistent<int, char>();
  285. ASSERT_TRUE((registry.contains<int, char>()));
  286. ASSERT_FALSE((registry.contains<int, double>()));
  287. registry.prepare<int, double>();
  288. ASSERT_TRUE((registry.contains<int, double>()));
  289. registry.discard<int, double>();
  290. ASSERT_FALSE((registry.contains<int, double>()));
  291. const auto e0 = registry.create();
  292. registry.assign<int>(e0, 0);
  293. registry.assign<char>(e0, 'c');
  294. const auto e1 = registry.create();
  295. registry.assign<int>(e1, 0);
  296. const auto e2 = registry.create();
  297. registry.assign<int>(e2, 0);
  298. registry.assign<char>(e2, 'c');
  299. decltype(view)::size_type cnt{0};
  300. view.each([&cnt](auto...) { ++cnt; });
  301. ASSERT_EQ(cnt, decltype(view)::size_type{2});
  302. }
  303. TEST(DefaultRegistry, CleanStandardViewsAfterReset) {
  304. entt::DefaultRegistry registry;
  305. auto view = registry.view<int>();
  306. registry.assign<int>(registry.create(), 0);
  307. ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{1});
  308. registry.reset();
  309. ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{0});
  310. }
  311. TEST(DefaultRegistry, CleanPersistentViewsAfterReset) {
  312. entt::DefaultRegistry registry;
  313. auto view = registry.persistent<int, char>();
  314. const auto entity = registry.create();
  315. registry.assign<int>(entity, 0);
  316. registry.assign<char>(entity, 'c');
  317. ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{1});
  318. registry.reset();
  319. ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{0});
  320. }
  321. TEST(DefaultRegistry, CleanTagsAfterReset) {
  322. entt::DefaultRegistry registry;
  323. const auto entity = registry.create();
  324. registry.assign<int>(entt::tag_type_t{}, entity);
  325. ASSERT_TRUE(registry.has<int>());
  326. registry.reset();
  327. ASSERT_FALSE(registry.has<int>());
  328. }
  329. TEST(DefaultRegistry, SortSingle) {
  330. entt::DefaultRegistry registry;
  331. int val = 0;
  332. registry.assign<int>(registry.create(), val++);
  333. registry.assign<int>(registry.create(), val++);
  334. registry.assign<int>(registry.create(), val++);
  335. for(auto entity: registry.view<int>()) {
  336. ASSERT_EQ(registry.get<int>(entity), --val);
  337. }
  338. registry.sort<int>(std::less<int>{});
  339. for(auto entity: registry.view<int>()) {
  340. ASSERT_EQ(registry.get<int>(entity), val++);
  341. }
  342. }
  343. TEST(DefaultRegistry, SortMulti) {
  344. entt::DefaultRegistry registry;
  345. unsigned int uval = 0u;
  346. int ival = 0;
  347. for(auto i = 0; i < 3; ++i) {
  348. const auto entity = registry.create();
  349. registry.assign<unsigned int>(entity, uval++);
  350. registry.assign<int>(entity, ival++);
  351. }
  352. for(auto entity: registry.view<unsigned int>()) {
  353. ASSERT_EQ(registry.get<unsigned int>(entity), --uval);
  354. }
  355. for(auto entity: registry.view<int>()) {
  356. ASSERT_EQ(registry.get<int>(entity), --ival);
  357. }
  358. registry.sort<unsigned int>(std::less<unsigned int>{});
  359. registry.sort<int, unsigned int>();
  360. for(auto entity: registry.view<unsigned int>()) {
  361. ASSERT_EQ(registry.get<unsigned int>(entity), uval++);
  362. }
  363. for(auto entity: registry.view<int>()) {
  364. ASSERT_EQ(registry.get<int>(entity), ival++);
  365. }
  366. }
  367. TEST(DefaultRegistry, ComponentsWithTypesFromStandardTemplateLibrary) {
  368. // see #37 - the test shouldn't crash, that's all
  369. entt::DefaultRegistry registry;
  370. const auto entity = registry.create();
  371. registry.assign<std::unordered_set<int>>(entity).insert(42);
  372. registry.destroy(entity);
  373. }
  374. TEST(DefaultRegistry, ConstructWithComponents) {
  375. // it should compile, that's all
  376. entt::DefaultRegistry registry;
  377. const auto value = 0;
  378. registry.assign<int>(registry.create(), value);
  379. }
  380. TEST(DefaultRegistry, MergeTwoRegistries) {
  381. using entity_type = entt::DefaultRegistry::entity_type;
  382. entt::DefaultRegistry src;
  383. entt::DefaultRegistry dst;
  384. std::unordered_map<entity_type, entity_type> ref;
  385. auto merge = [&ref](const auto &view, auto &dst) {
  386. view.each([&](auto entity, const auto &component) {
  387. if(ref.find(entity) == ref.cend()) {
  388. const auto other = dst.create();
  389. dst.template assign<std::decay_t<decltype(component)>>(other, component);
  390. ref.emplace(entity, other);
  391. } else {
  392. using component_type = std::decay_t<decltype(component)>;
  393. dst.template assign<component_type>(ref[entity], component);
  394. }
  395. });
  396. };
  397. auto e0 = src.create();
  398. src.assign<int>(e0);
  399. src.assign<float>(e0);
  400. src.assign<double>(e0);
  401. auto e1 = src.create();
  402. src.assign<char>(e1);
  403. src.assign<float>(e1);
  404. src.assign<int>(e1);
  405. auto e2 = dst.create();
  406. dst.assign<int>(e2);
  407. dst.assign<char>(e2);
  408. dst.assign<double>(e2);
  409. auto e3 = dst.create();
  410. dst.assign<float>(e3);
  411. dst.assign<int>(e3);
  412. auto eq = [](auto begin, auto end) { ASSERT_EQ(begin, end); };
  413. auto ne = [](auto begin, auto end) { ASSERT_NE(begin, end); };
  414. eq(dst.view<int, float, double>().begin(), dst.view<int, float, double>().end());
  415. eq(dst.view<char, float, int>().begin(), dst.view<char, float, int>().end());
  416. merge(src.view<int>(), dst);
  417. merge(src.view<char>(), dst);
  418. merge(src.view<double>(), dst);
  419. merge(src.view<float>(), dst);
  420. ne(dst.view<int, float, double>().begin(), dst.view<int, float, double>().end());
  421. ne(dst.view<char, float, int>().begin(), dst.view<char, float, int>().end());
  422. }
  423. TEST(DefaultRegistry, Signals) {
  424. entt::DefaultRegistry registry;
  425. ComponentListener listener;
  426. registry.construction<int>().connect<ComponentListener, &ComponentListener::incr>(&listener);
  427. registry.destruction<int>().connect<ComponentListener, &ComponentListener::decr>(&listener);
  428. auto e0 = registry.create();
  429. auto e1 = registry.create();
  430. registry.assign<int>(e0);
  431. registry.assign<int>(e1);
  432. ASSERT_EQ(listener.counter, 2);
  433. ASSERT_EQ(listener.last, e1);
  434. registry.remove<int>(e0);
  435. ASSERT_EQ(listener.counter, 1);
  436. ASSERT_EQ(listener.last, e0);
  437. registry.destruction<int>().disconnect<ComponentListener, &ComponentListener::decr>(&listener);
  438. registry.remove<int>(e1);
  439. ASSERT_EQ(listener.counter, 1);
  440. ASSERT_EQ(listener.last, e0);
  441. registry.construction<int>().disconnect<ComponentListener, &ComponentListener::incr>(&listener);
  442. registry.assign<int>(e0);
  443. registry.assign<int>(e1);
  444. ASSERT_EQ(listener.counter, 1);
  445. ASSERT_EQ(listener.last, e0);
  446. }