ax_tree_serializer_unittest.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/accessibility/ax_tree_serializer.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <memory>
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/strings/string_number_conversions.h"
  10. #include "base/strings/stringprintf.h"
  11. #include "testing/gmock/include/gmock/gmock-matchers.h"
  12. #include "testing/gtest/include/gtest/gtest.h"
  13. #include "ui/accessibility/ax_node.h"
  14. #include "ui/accessibility/ax_serializable_tree.h"
  15. using testing::UnorderedElementsAre;
  16. namespace ui {
  17. using BasicAXTreeSerializer = AXTreeSerializer<const AXNode*>;
  18. // The framework for these tests is that each test sets up |treedata0_|
  19. // and |treedata1_| and then calls GetTreeSerializer, which creates a
  20. // serializer for a tree that's initially in state |treedata0_|, but then
  21. // changes to state |treedata1_|. This allows each test to check the
  22. // updates created by AXTreeSerializer or unit-test its private
  23. // member functions.
  24. class AXTreeSerializerTest : public testing::Test {
  25. public:
  26. AXTreeSerializerTest() {}
  27. AXTreeSerializerTest(const AXTreeSerializerTest&) = delete;
  28. AXTreeSerializerTest& operator=(const AXTreeSerializerTest&) = delete;
  29. ~AXTreeSerializerTest() override {}
  30. protected:
  31. void CreateTreeSerializer();
  32. AXTreeUpdate treedata0_;
  33. AXTreeUpdate treedata1_;
  34. std::unique_ptr<AXSerializableTree> tree0_;
  35. std::unique_ptr<AXSerializableTree> tree1_;
  36. std::unique_ptr<AXTreeSource<const AXNode*>> tree0_source_;
  37. std::unique_ptr<AXTreeSource<const AXNode*>> tree1_source_;
  38. std::unique_ptr<BasicAXTreeSerializer> serializer_;
  39. };
  40. void AXTreeSerializerTest::CreateTreeSerializer() {
  41. if (serializer_)
  42. return;
  43. tree0_ = std::make_unique<AXSerializableTree>(treedata0_);
  44. tree1_ = std::make_unique<AXSerializableTree>(treedata1_);
  45. // Serialize tree0 so that AXTreeSerializer thinks that its client
  46. // is totally in sync.
  47. tree0_source_.reset(tree0_->CreateTreeSource());
  48. serializer_ = std::make_unique<BasicAXTreeSerializer>(tree0_source_.get());
  49. AXTreeUpdate unused_update;
  50. ASSERT_TRUE(serializer_->SerializeChanges(tree0_->root(), &unused_update));
  51. // Pretend that tree0_ turned into tree1_. The next call to
  52. // AXTreeSerializer will force it to consider these changes to
  53. // the tree and send them as part of the next update.
  54. tree1_source_.reset(tree1_->CreateTreeSource());
  55. serializer_->ChangeTreeSourceForTesting(tree1_source_.get());
  56. }
  57. // In this test, one child is added to the root. Only the root and
  58. // new child should be added.
  59. TEST_F(AXTreeSerializerTest, UpdateContainsOnlyChangedNodes) {
  60. // (1 (2 3))
  61. treedata0_.root_id = 1;
  62. treedata0_.nodes.resize(3);
  63. treedata0_.nodes[0].id = 1;
  64. treedata0_.nodes[0].child_ids.push_back(2);
  65. treedata0_.nodes[0].child_ids.push_back(3);
  66. treedata0_.nodes[1].id = 2;
  67. treedata0_.nodes[2].id = 3;
  68. // (1 (4 2 3))
  69. treedata1_.root_id = 1;
  70. treedata1_.nodes.resize(4);
  71. treedata1_.nodes[0].id = 1;
  72. treedata1_.nodes[0].child_ids.push_back(4);
  73. treedata1_.nodes[0].child_ids.push_back(2);
  74. treedata1_.nodes[0].child_ids.push_back(3);
  75. treedata1_.nodes[1].id = 2;
  76. treedata1_.nodes[2].id = 3;
  77. treedata1_.nodes[3].id = 4;
  78. CreateTreeSerializer();
  79. AXTreeUpdate update;
  80. ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(1), &update));
  81. // The update should only touch nodes 1 and 4 - nodes 2 and 3 are unchanged
  82. // and shouldn't be affected.
  83. EXPECT_EQ(0, update.node_id_to_clear);
  84. ASSERT_EQ(2u, update.nodes.size());
  85. EXPECT_EQ(1, update.nodes[0].id);
  86. EXPECT_EQ(4, update.nodes[1].id);
  87. }
  88. // When the root changes, the whole tree is updated, even if some of it
  89. // is unaffected.
  90. TEST_F(AXTreeSerializerTest, NewRootUpdatesEntireTree) {
  91. // (1 (2 (3 (4))))
  92. treedata0_.root_id = 1;
  93. treedata0_.nodes.resize(4);
  94. treedata0_.nodes[0].id = 1;
  95. treedata0_.nodes[0].child_ids.push_back(2);
  96. treedata0_.nodes[1].id = 2;
  97. treedata0_.nodes[1].child_ids.push_back(3);
  98. treedata0_.nodes[2].id = 3;
  99. treedata0_.nodes[2].child_ids.push_back(4);
  100. treedata0_.nodes[3].id = 4;
  101. // (5 (2 (3 (4))))
  102. treedata1_.root_id = 5;
  103. treedata1_.nodes.resize(4);
  104. treedata1_.nodes[0].id = 5;
  105. treedata1_.nodes[0].child_ids.push_back(2);
  106. treedata1_.nodes[1].id = 2;
  107. treedata1_.nodes[1].child_ids.push_back(3);
  108. treedata1_.nodes[2].id = 3;
  109. treedata1_.nodes[2].child_ids.push_back(4);
  110. treedata1_.nodes[3].id = 4;
  111. CreateTreeSerializer();
  112. AXTreeUpdate update;
  113. ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(4), &update));
  114. // The update should delete the subtree rooted at node id=1, and
  115. // then include all four nodes in the update, even though the
  116. // subtree rooted at id=2 didn't actually change.
  117. EXPECT_EQ(1, update.node_id_to_clear);
  118. ASSERT_EQ(4u, update.nodes.size());
  119. EXPECT_EQ(5, update.nodes[0].id);
  120. EXPECT_EQ(2, update.nodes[1].id);
  121. EXPECT_EQ(3, update.nodes[2].id);
  122. EXPECT_EQ(4, update.nodes[3].id);
  123. }
  124. // When a node is reparented, the subtree including both the old parent
  125. // and new parent of the reparented node must be deleted and recreated.
  126. TEST_F(AXTreeSerializerTest, ReparentingUpdatesSubtree) {
  127. // (1 (2 (3 (4) 5)))
  128. treedata0_.root_id = 1;
  129. treedata0_.nodes.resize(5);
  130. treedata0_.nodes[0].id = 1;
  131. treedata0_.nodes[0].child_ids.push_back(2);
  132. treedata0_.nodes[1].id = 2;
  133. treedata0_.nodes[1].child_ids.push_back(3);
  134. treedata0_.nodes[1].child_ids.push_back(5);
  135. treedata0_.nodes[2].id = 3;
  136. treedata0_.nodes[2].child_ids.push_back(4);
  137. treedata0_.nodes[3].id = 4;
  138. treedata0_.nodes[4].id = 5;
  139. // Node 5 has been reparented from being a child of node 2,
  140. // to a child of node 4.
  141. // (1 (2 (3 (4 (5)))))
  142. treedata1_.root_id = 1;
  143. treedata1_.nodes.resize(5);
  144. treedata1_.nodes[0].id = 1;
  145. treedata1_.nodes[0].child_ids.push_back(2);
  146. treedata1_.nodes[1].id = 2;
  147. treedata1_.nodes[1].child_ids.push_back(3);
  148. treedata1_.nodes[2].id = 3;
  149. treedata1_.nodes[2].child_ids.push_back(4);
  150. treedata1_.nodes[3].id = 4;
  151. treedata1_.nodes[3].child_ids.push_back(5);
  152. treedata1_.nodes[4].id = 5;
  153. CreateTreeSerializer();
  154. AXTreeUpdate update;
  155. ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(4), &update));
  156. // The update should unserialize without errors.
  157. AXTree dst_tree(treedata0_);
  158. EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error();
  159. // The update should delete the subtree rooted at node id=2, and
  160. // then include nodes 2...5.
  161. EXPECT_EQ(2, update.node_id_to_clear);
  162. ASSERT_EQ(4u, update.nodes.size());
  163. EXPECT_EQ(2, update.nodes[0].id);
  164. EXPECT_EQ(3, update.nodes[1].id);
  165. EXPECT_EQ(4, update.nodes[2].id);
  166. EXPECT_EQ(5, update.nodes[3].id);
  167. }
  168. // Similar to ReparentingUpdatesSubtree, except that InvalidateSubtree is
  169. // called on id=1 - we need to make sure that the reparenting is still
  170. // detected.
  171. TEST_F(AXTreeSerializerTest, ReparentingWithInvalidationUpdatesSubtree) {
  172. // (1 (2 (3 (4 (5)))))
  173. treedata0_.root_id = 1;
  174. treedata0_.nodes.resize(5);
  175. treedata0_.nodes[0].id = 1;
  176. treedata0_.nodes[0].child_ids.push_back(2);
  177. treedata0_.nodes[1].id = 2;
  178. treedata0_.nodes[1].child_ids.push_back(3);
  179. treedata0_.nodes[2].id = 3;
  180. treedata0_.nodes[2].child_ids.push_back(4);
  181. treedata0_.nodes[3].id = 4;
  182. treedata0_.nodes[3].child_ids.push_back(5);
  183. treedata0_.nodes[4].id = 5;
  184. // Node 5 has been reparented from being a child of node 4,
  185. // to a child of node 2.
  186. // (1 (2 (3 (4) 5)))
  187. treedata1_.root_id = 1;
  188. treedata1_.nodes.resize(5);
  189. treedata1_.nodes[0].id = 1;
  190. treedata1_.nodes[0].child_ids.push_back(2);
  191. treedata1_.nodes[1].id = 2;
  192. treedata1_.nodes[1].child_ids.push_back(3);
  193. treedata1_.nodes[1].child_ids.push_back(5);
  194. treedata1_.nodes[2].id = 3;
  195. treedata1_.nodes[2].child_ids.push_back(4);
  196. treedata1_.nodes[3].id = 4;
  197. treedata1_.nodes[4].id = 5;
  198. CreateTreeSerializer();
  199. AXTreeUpdate update;
  200. serializer_->InvalidateSubtree(tree1_->GetFromId(1));
  201. ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(4), &update));
  202. // The update should unserialize without errors.
  203. AXTree dst_tree(treedata0_);
  204. EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error();
  205. }
  206. // A variant of AXTreeSource that returns true for IsValid() for one
  207. // particular id.
  208. class AXTreeSourceWithInvalidId : public AXTreeSource<const AXNode*> {
  209. public:
  210. AXTreeSourceWithInvalidId(AXTree* tree, int invalid_id)
  211. : tree_(tree),
  212. invalid_id_(invalid_id) {}
  213. AXTreeSourceWithInvalidId(const AXTreeSourceWithInvalidId&) = delete;
  214. AXTreeSourceWithInvalidId& operator=(const AXTreeSourceWithInvalidId&) =
  215. delete;
  216. ~AXTreeSourceWithInvalidId() override {}
  217. // AXTreeSource implementation.
  218. bool GetTreeData(AXTreeData* data) const override {
  219. *data = AXTreeData();
  220. return true;
  221. }
  222. AXNode* GetRoot() const override { return tree_->root(); }
  223. AXNode* GetFromId(AXNodeID id) const override { return tree_->GetFromId(id); }
  224. AXNodeID GetId(const AXNode* node) const override { return node->id(); }
  225. void GetChildren(const AXNode* node,
  226. std::vector<const AXNode*>* out_children) const override {
  227. *out_children = std::vector<const AXNode*>(node->children().cbegin(),
  228. node->children().cend());
  229. }
  230. AXNode* GetParent(const AXNode* node) const override {
  231. return node->parent();
  232. }
  233. bool IsIgnored(const AXNode* node) const override {
  234. return node->IsIgnored();
  235. }
  236. bool IsValid(const AXNode* node) const override {
  237. return node != nullptr && node->id() != invalid_id_;
  238. }
  239. bool IsEqual(const AXNode* node1, const AXNode* node2) const override {
  240. return node1 == node2;
  241. }
  242. const AXNode* GetNull() const override { return nullptr; }
  243. void SerializeNode(const AXNode* node, AXNodeData* out_data) const override {
  244. *out_data = node->data();
  245. if (node->id() == invalid_id_)
  246. out_data->id = -1;
  247. }
  248. private:
  249. raw_ptr<AXTree> tree_;
  250. int invalid_id_;
  251. };
  252. // Test that the serializer skips invalid children.
  253. TEST(AXTreeSerializerInvalidTest, InvalidChild) {
  254. // (1 (2 3))
  255. AXTreeUpdate treedata;
  256. treedata.root_id = 1;
  257. treedata.nodes.resize(3);
  258. treedata.nodes[0].id = 1;
  259. treedata.nodes[0].child_ids.push_back(2);
  260. treedata.nodes[0].child_ids.push_back(3);
  261. treedata.nodes[1].id = 2;
  262. treedata.nodes[2].id = 3;
  263. AXTree tree(treedata);
  264. AXTreeSourceWithInvalidId source(&tree, 3);
  265. BasicAXTreeSerializer serializer(&source);
  266. AXTreeUpdate update;
  267. ASSERT_TRUE(serializer.SerializeChanges(tree.root(), &update));
  268. ASSERT_EQ(2U, update.nodes.size());
  269. EXPECT_EQ(1, update.nodes[0].id);
  270. EXPECT_EQ(2, update.nodes[1].id);
  271. }
  272. // Test that we can set a maximum number of nodes to serialize.
  273. TEST_F(AXTreeSerializerTest, MaximumSerializedNodeCount) {
  274. // (1 (2 (3 4) 5 (6 7)))
  275. treedata0_.root_id = 1;
  276. treedata0_.nodes.resize(7);
  277. treedata0_.nodes[0].id = 1;
  278. treedata0_.nodes[0].child_ids.push_back(2);
  279. treedata0_.nodes[0].child_ids.push_back(5);
  280. treedata0_.nodes[1].id = 2;
  281. treedata0_.nodes[1].child_ids.push_back(3);
  282. treedata0_.nodes[1].child_ids.push_back(4);
  283. treedata0_.nodes[2].id = 3;
  284. treedata0_.nodes[3].id = 4;
  285. treedata0_.nodes[4].id = 5;
  286. treedata0_.nodes[4].child_ids.push_back(6);
  287. treedata0_.nodes[4].child_ids.push_back(7);
  288. treedata0_.nodes[5].id = 6;
  289. treedata0_.nodes[6].id = 7;
  290. tree0_ = std::make_unique<AXSerializableTree>(treedata0_);
  291. tree0_source_.reset(tree0_->CreateTreeSource());
  292. serializer_ = std::make_unique<BasicAXTreeSerializer>(tree0_source_.get());
  293. serializer_->set_max_node_count(4);
  294. AXTreeUpdate update;
  295. ASSERT_TRUE(serializer_->SerializeChanges(tree0_->root(), &update));
  296. // It actually serializes 5 nodes, not 4 - to be consistent.
  297. // It skips the children of node 5.
  298. ASSERT_EQ(5u, update.nodes.size());
  299. }
  300. #if defined(GTEST_HAS_DEATH_TEST)
  301. // If duplicate ids are encountered, it crashes via CHECK(false).
  302. TEST_F(AXTreeSerializerTest, DuplicateIdsCrashes) {
  303. // (1 (2 (3 (4) 5)))
  304. treedata0_.root_id = 1;
  305. treedata0_.nodes.resize(5);
  306. treedata0_.nodes[0].id = 1;
  307. treedata0_.nodes[0].child_ids.push_back(2);
  308. treedata0_.nodes[1].id = 2;
  309. treedata0_.nodes[1].child_ids.push_back(3);
  310. treedata0_.nodes[1].child_ids.push_back(5);
  311. treedata0_.nodes[2].id = 3;
  312. treedata0_.nodes[2].child_ids.push_back(4);
  313. treedata0_.nodes[3].id = 4;
  314. treedata0_.nodes[4].id = 5;
  315. // (1 (2 (6 (7) 5)))
  316. treedata1_.root_id = 1;
  317. treedata1_.nodes.resize(5);
  318. treedata1_.nodes[0].id = 1;
  319. treedata1_.nodes[0].child_ids.push_back(2);
  320. treedata1_.nodes[1].id = 2;
  321. treedata1_.nodes[1].child_ids.push_back(6);
  322. treedata1_.nodes[1].child_ids.push_back(5);
  323. treedata1_.nodes[2].id = 6;
  324. treedata1_.nodes[2].child_ids.push_back(7);
  325. treedata1_.nodes[3].id = 7;
  326. treedata1_.nodes[4].id = 5;
  327. CreateTreeSerializer();
  328. // Do some open-heart surgery on tree1, giving it a duplicate node.
  329. // This could not happen with an AXTree, but could happen with
  330. // another AXTreeSource if the structure it wraps is buggy. We want to
  331. // fail but not crash when that happens.
  332. std::vector<AXNode*> node2_children;
  333. node2_children.push_back(tree1_->GetFromId(7));
  334. node2_children.push_back(tree1_->GetFromId(6));
  335. tree1_->GetFromId(2)->SwapChildren(&node2_children);
  336. AXTreeUpdate update;
  337. EXPECT_DEATH(serializer_->SerializeChanges(tree1_->GetFromId(7), &update),
  338. "");
  339. // Swap it back, fixing the tree. Given the above crash, this is just to
  340. // ensure the test can clean up properly and avoid a different failure.
  341. tree1_->GetFromId(2)->SwapChildren(&node2_children);
  342. update = AXTreeUpdate();
  343. EXPECT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(7), &update));
  344. }
  345. #endif
  346. // If a tree serializer is reset, that means it doesn't know about
  347. // the state of the client tree anymore. The safest thing to do in
  348. // that circumstance is to force the client to clear everything.
  349. TEST_F(AXTreeSerializerTest, ResetUpdatesNodeIdToClear) {
  350. // (1 (2 (3 (4 (5)))))
  351. treedata0_.root_id = 1;
  352. treedata0_.nodes.resize(5);
  353. treedata0_.nodes[0].id = 1;
  354. treedata0_.nodes[0].child_ids.push_back(2);
  355. treedata0_.nodes[1].id = 2;
  356. treedata0_.nodes[1].child_ids.push_back(3);
  357. treedata0_.nodes[2].id = 3;
  358. treedata0_.nodes[2].child_ids.push_back(4);
  359. treedata0_.nodes[3].id = 4;
  360. treedata0_.nodes[3].child_ids.push_back(5);
  361. treedata0_.nodes[4].id = 5;
  362. // Node 5 has been reparented from being a child of node 4,
  363. // to a child of node 2.
  364. // (1 (2 (3 (4) 5)))
  365. treedata1_.root_id = 1;
  366. treedata1_.nodes.resize(5);
  367. treedata1_.nodes[0].id = 1;
  368. treedata1_.nodes[0].child_ids.push_back(2);
  369. treedata1_.nodes[1].id = 2;
  370. treedata1_.nodes[1].child_ids.push_back(3);
  371. treedata1_.nodes[1].child_ids.push_back(5);
  372. treedata1_.nodes[2].id = 3;
  373. treedata1_.nodes[2].child_ids.push_back(4);
  374. treedata1_.nodes[3].id = 4;
  375. treedata1_.nodes[4].id = 5;
  376. CreateTreeSerializer();
  377. serializer_->Reset();
  378. AXTreeUpdate update;
  379. ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(4), &update));
  380. // The update should unserialize without errors.
  381. AXTree dst_tree(treedata0_);
  382. EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error();
  383. }
  384. // Ensure that calling Reset doesn't cause any problems if
  385. // the root changes.
  386. TEST_F(AXTreeSerializerTest, ResetWorksWithNewRootId) {
  387. // (1 (2))
  388. treedata0_.root_id = 1;
  389. treedata0_.nodes.resize(2);
  390. treedata0_.nodes[0].id = 1;
  391. treedata0_.nodes[0].child_ids.push_back(2);
  392. treedata0_.nodes[1].id = 2;
  393. // (3 (4))
  394. treedata1_.root_id = 3;
  395. treedata1_.nodes.resize(2);
  396. treedata1_.nodes[0].id = 3;
  397. treedata1_.nodes[0].child_ids.push_back(4);
  398. treedata1_.nodes[1].id = 4;
  399. CreateTreeSerializer();
  400. serializer_->Reset();
  401. AXTreeUpdate update;
  402. ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(4), &update));
  403. // The update should unserialize without errors.
  404. AXTree dst_tree(treedata0_);
  405. EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error();
  406. }
  407. // Wraps an AXTreeSource and provides access to the results of the
  408. // SerializerClearedNode callback.
  409. class AXTreeSourceTestWrapper : public AXTreeSource<const AXNode*> {
  410. public:
  411. explicit AXTreeSourceTestWrapper(AXTreeSource<const AXNode*>* tree_source)
  412. : tree_source_(tree_source) {}
  413. ~AXTreeSourceTestWrapper() override = default;
  414. // Override SerializerClearedNode and provide a way to access it.
  415. void SerializerClearedNode(AXNodeID node_id) override {
  416. cleared_node_ids_.insert(node_id);
  417. }
  418. void ClearClearedNodeIds() { cleared_node_ids_.clear(); }
  419. std::set<AXNodeID>& cleared_node_ids() { return cleared_node_ids_; }
  420. // The rest of the AXTreeSource implementation just calls through to
  421. // tree_source_.
  422. bool GetTreeData(AXTreeData* data) const override {
  423. return tree_source_->GetTreeData(data);
  424. }
  425. const AXNode* GetRoot() const override { return tree_source_->GetRoot(); }
  426. const AXNode* GetFromId(AXNodeID id) const override {
  427. return tree_source_->GetFromId(id);
  428. }
  429. AXNodeID GetId(const AXNode* node) const override {
  430. return tree_source_->GetId(node);
  431. }
  432. void GetChildren(const AXNode* node,
  433. std::vector<const AXNode*>* out_children) const override {
  434. return tree_source_->GetChildren(node, out_children);
  435. }
  436. const AXNode* GetParent(const AXNode* node) const override {
  437. return tree_source_->GetParent(node);
  438. }
  439. bool IsIgnored(const AXNode* node) const override {
  440. return tree_source_->IsIgnored(node);
  441. }
  442. bool IsValid(const AXNode* node) const override {
  443. return tree_source_->IsValid(node);
  444. }
  445. bool IsEqual(const AXNode* node1, const AXNode* node2) const override {
  446. return tree_source_->IsEqual(node1, node2);
  447. }
  448. const AXNode* GetNull() const override { return tree_source_->GetNull(); }
  449. void SerializeNode(const AXNode* node, AXNodeData* out_data) const override {
  450. tree_source_->SerializeNode(node, out_data);
  451. }
  452. private:
  453. raw_ptr<AXTreeSource<const AXNode*>> tree_source_;
  454. std::set<AXNodeID> cleared_node_ids_;
  455. };
  456. TEST_F(AXTreeSerializerTest, TestClearedNodesWhenUpdatingRoot) {
  457. // (1 (2 (3 (4))))
  458. treedata0_.root_id = 1;
  459. treedata0_.nodes.resize(4);
  460. treedata0_.nodes[0].id = 1;
  461. treedata0_.nodes[0].child_ids.push_back(2);
  462. treedata0_.nodes[1].id = 2;
  463. treedata0_.nodes[1].child_ids.push_back(3);
  464. treedata0_.nodes[2].id = 3;
  465. treedata0_.nodes[2].child_ids.push_back(4);
  466. treedata0_.nodes[3].id = 4;
  467. // (5 (2 (3 (4))))
  468. treedata1_.root_id = 5;
  469. treedata1_.nodes.resize(4);
  470. treedata1_.nodes[0].id = 5;
  471. treedata1_.nodes[0].child_ids.push_back(2);
  472. treedata1_.nodes[1].id = 2;
  473. treedata1_.nodes[1].child_ids.push_back(3);
  474. treedata1_.nodes[2].id = 3;
  475. treedata1_.nodes[2].child_ids.push_back(4);
  476. treedata1_.nodes[3].id = 4;
  477. // Similar sequence to CreateTreeSerializer, but using
  478. // AXTreeSourceTestWrapper instead.
  479. tree0_ = std::make_unique<AXSerializableTree>(treedata0_);
  480. tree1_ = std::make_unique<AXSerializableTree>(treedata1_);
  481. tree0_source_.reset(tree0_->CreateTreeSource());
  482. AXTreeSourceTestWrapper tree0_source_wrapper(tree0_source_.get());
  483. serializer_ = std::make_unique<BasicAXTreeSerializer>(&tree0_source_wrapper);
  484. AXTreeUpdate unused_update;
  485. ASSERT_TRUE(serializer_->SerializeChanges(tree0_->root(), &unused_update));
  486. tree1_source_.reset(tree1_->CreateTreeSource());
  487. AXTreeSourceTestWrapper tree1_source_wrapper(tree1_source_.get());
  488. serializer_->ChangeTreeSourceForTesting(&tree1_source_wrapper);
  489. ASSERT_EQ(4U, serializer_->ClientTreeNodeCount());
  490. // If we swap out the root, all of the node IDs should have
  491. // SerializerClearedNode called on them.
  492. tree1_source_wrapper.ClearClearedNodeIds();
  493. ASSERT_TRUE(serializer_->SerializeChanges(tree1_->root(), &unused_update));
  494. EXPECT_THAT(tree1_source_wrapper.cleared_node_ids(),
  495. UnorderedElementsAre(1, 2, 3, 4));
  496. // Destroy the serializer first so that the AXTreeSources it points to
  497. // don't go out of scope first.
  498. serializer_.reset();
  499. }
  500. TEST_F(AXTreeSerializerTest, TestClearedNodesWhenUpdatingBranch) {
  501. // (1 (2 (3 (4))))
  502. treedata0_.root_id = 1;
  503. treedata0_.nodes.resize(4);
  504. treedata0_.nodes[0].id = 1;
  505. treedata0_.nodes[0].child_ids.push_back(2);
  506. treedata0_.nodes[1].id = 2;
  507. treedata0_.nodes[1].child_ids.push_back(3);
  508. treedata0_.nodes[2].id = 3;
  509. treedata0_.nodes[2].child_ids.push_back(4);
  510. treedata0_.nodes[3].id = 4;
  511. // (1 (2 (5 (6))))
  512. treedata1_.root_id = 1;
  513. treedata1_.nodes.resize(4);
  514. treedata1_.nodes[0].id = 1;
  515. treedata1_.nodes[0].child_ids.push_back(2);
  516. treedata1_.nodes[1].id = 2;
  517. treedata1_.nodes[1].child_ids.push_back(5);
  518. treedata1_.nodes[2].id = 5;
  519. treedata1_.nodes[2].child_ids.push_back(6);
  520. treedata1_.nodes[3].id = 6;
  521. // Similar sequence to CreateTreeSerializer, but using
  522. // AXTreeSourceTestWrapper instead.
  523. tree0_ = std::make_unique<AXSerializableTree>(treedata0_);
  524. tree1_ = std::make_unique<AXSerializableTree>(treedata1_);
  525. tree0_source_.reset(tree0_->CreateTreeSource());
  526. AXTreeSourceTestWrapper tree0_source_wrapper(tree0_source_.get());
  527. serializer_ = std::make_unique<BasicAXTreeSerializer>(&tree0_source_wrapper);
  528. AXTreeUpdate unused_update;
  529. ASSERT_TRUE(serializer_->SerializeChanges(tree0_->root(), &unused_update));
  530. tree1_source_.reset(tree1_->CreateTreeSource());
  531. AXTreeSourceTestWrapper tree1_source_wrapper(tree1_source_.get());
  532. serializer_->ChangeTreeSourceForTesting(&tree1_source_wrapper);
  533. ASSERT_EQ(4U, serializer_->ClientTreeNodeCount());
  534. // If we replace one branch with another, we should get calls to
  535. // SerializerClearedNode with all of the node IDs no longer in the tree.
  536. tree1_source_wrapper.ClearClearedNodeIds();
  537. ASSERT_TRUE(
  538. serializer_->SerializeChanges(tree1_->GetFromId(2), &unused_update));
  539. EXPECT_THAT(tree1_source_wrapper.cleared_node_ids(),
  540. UnorderedElementsAre(3, 4));
  541. // Destroy the serializer first so that the AXTreeSources it points to
  542. // don't go out of scope first.
  543. serializer_.reset();
  544. }
  545. TEST_F(AXTreeSerializerTest, TestPartialSerialization) {
  546. // Serialize only part of the tree.
  547. // (1)
  548. treedata0_.root_id = 1;
  549. treedata0_.nodes.resize(1);
  550. treedata0_.nodes[0].id = 1;
  551. // (1 (2 (3 4)) (5 (6 7)))
  552. treedata1_.root_id = 1;
  553. treedata1_.nodes.resize(7);
  554. treedata1_.nodes[0].id = 1;
  555. treedata1_.nodes[0].child_ids = {2, 5};
  556. treedata1_.nodes[1].id = 2;
  557. treedata1_.nodes[1].child_ids = {3, 4};
  558. treedata1_.nodes[2].id = 3;
  559. treedata1_.nodes[3].id = 4;
  560. treedata1_.nodes[4].id = 5;
  561. treedata1_.nodes[4].child_ids = {6, 7};
  562. treedata1_.nodes[5].id = 6;
  563. treedata1_.nodes[6].id = 7;
  564. for (int max_node_count = 1; max_node_count <= 4; max_node_count++) {
  565. SCOPED_TRACE(base::StringPrintf("Max node count: %d", max_node_count));
  566. CreateTreeSerializer();
  567. serializer_->Reset();
  568. serializer_->set_max_node_count(max_node_count);
  569. AXTreeUpdate update;
  570. ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(1), &update));
  571. // The update should unserialize without errors.
  572. AXSerializableTree dst_tree(treedata0_);
  573. EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error();
  574. // The tree should be incomplete; it should have too few nodes.
  575. EXPECT_LT(update.nodes.size(), treedata1_.nodes.size());
  576. EXPECT_LT(dst_tree.size(), static_cast<int>(treedata1_.nodes.size()));
  577. // The serializer should give us a list of nodes that have yet to
  578. // be serialized.
  579. std::vector<AXNodeID> incomplete_node_ids =
  580. serializer_->GetIncompleteNodeIds();
  581. EXPECT_FALSE(incomplete_node_ids.empty());
  582. // Serialize the incomplete nodes, with no more limit.
  583. serializer_->set_max_node_count(0);
  584. for (AXNodeID id : incomplete_node_ids) {
  585. update = AXTreeUpdate();
  586. ASSERT_TRUE(
  587. serializer_->SerializeChanges(tree1_->GetFromId(id), &update));
  588. EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error();
  589. }
  590. // The result should be indistinguishable from the source tree.
  591. std::unique_ptr<AXTreeSource<const AXNode*>> dst_tree_source(
  592. dst_tree.CreateTreeSource());
  593. AXTreeSerializer<const AXNode*> serializer(dst_tree_source.get());
  594. AXTreeUpdate dst_update;
  595. CHECK(serializer.SerializeChanges(dst_tree.root(), &dst_update));
  596. ASSERT_EQ(treedata1_.ToString(), dst_update.ToString());
  597. }
  598. }
  599. } // namespace ui