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 5 #include "base/memory/scoped_ptr.h" 6 #include "base/strings/string_number_conversions.h" 7 #include "testing/gtest/include/gtest/gtest.h" 8 #include "ui/accessibility/ax_node.h" 9 #include "ui/accessibility/ax_serializable_tree.h" 10 #include "ui/accessibility/ax_tree.h" 11 #include "ui/accessibility/ax_tree_serializer.h" 12 13 namespace ui { 14 15 TEST(AXTreeTest, SerializeSimpleAXTree) { 16 AXNodeData root; 17 root.id = 1; 18 root.role = AX_ROLE_ROOT_WEB_AREA; 19 root.child_ids.push_back(2); 20 root.child_ids.push_back(3); 21 22 AXNodeData button; 23 button.id = 2; 24 button.role = AX_ROLE_BUTTON; 25 button.state = 0; 26 27 AXNodeData checkbox; 28 checkbox.id = 3; 29 checkbox.role = AX_ROLE_CHECK_BOX; 30 31 AXTreeUpdate initial_state; 32 initial_state.nodes.push_back(root); 33 initial_state.nodes.push_back(button); 34 initial_state.nodes.push_back(checkbox); 35 AXSerializableTree src_tree(initial_state); 36 37 scoped_ptr<AXTreeSource<AXNode> > tree_source( 38 src_tree.CreateTreeSource()); 39 AXTreeSerializer<AXNode> serializer(tree_source.get()); 40 AXTreeUpdate update; 41 serializer.SerializeChanges(src_tree.GetRoot(), &update); 42 43 AXTree dst_tree; 44 ASSERT_TRUE(dst_tree.Unserialize(update)); 45 46 AXNode* root_node = dst_tree.GetRoot(); 47 ASSERT_TRUE(root_node != NULL); 48 EXPECT_EQ(root.id, root_node->id()); 49 EXPECT_EQ(root.role, root_node->data().role); 50 51 ASSERT_EQ(2, root_node->child_count()); 52 53 AXNode* button_node = root_node->ChildAtIndex(0); 54 EXPECT_EQ(button.id, button_node->id()); 55 EXPECT_EQ(button.role, button_node->data().role); 56 57 AXNode* checkbox_node = root_node->ChildAtIndex(1); 58 EXPECT_EQ(checkbox.id, checkbox_node->id()); 59 EXPECT_EQ(checkbox.role, checkbox_node->data().role); 60 } 61 62 TEST(AXTreeTest, DeleteUnknownSubtreeFails) { 63 AXNodeData root; 64 root.id = 1; 65 root.role = AX_ROLE_ROOT_WEB_AREA; 66 67 AXTreeUpdate initial_state; 68 initial_state.nodes.push_back(root); 69 AXTree tree(initial_state); 70 71 // This should fail because we're asking it to delete 72 // a subtree rooted at id=2, which doesn't exist. 73 AXTreeUpdate update; 74 update.node_id_to_clear = 2; 75 update.nodes.resize(1); 76 update.nodes[0].id = 1; 77 update.nodes[0].id = AX_ROLE_ROOT_WEB_AREA; 78 EXPECT_FALSE(tree.Unserialize(update)); 79 ASSERT_EQ("Bad node_id_to_clear: 2", tree.error()); 80 } 81 82 TEST(AXTreeTest, LeaveOrphanedDeletedSubtreeFails) { 83 AXTreeUpdate initial_state; 84 initial_state.nodes.resize(3); 85 initial_state.nodes[0].id = 1; 86 initial_state.nodes[0].role = AX_ROLE_ROOT_WEB_AREA; 87 initial_state.nodes[0].child_ids.push_back(2); 88 initial_state.nodes[0].child_ids.push_back(3); 89 initial_state.nodes[1].id = 2; 90 initial_state.nodes[2].id = 3; 91 AXTree tree(initial_state); 92 93 // This should fail because we delete a subtree rooted at id=2 94 // but never update it. 95 AXTreeUpdate update; 96 update.node_id_to_clear = 2; 97 update.nodes.resize(1); 98 update.nodes[0].id = 3; 99 EXPECT_FALSE(tree.Unserialize(update)); 100 ASSERT_EQ("Nodes left pending by the update: 2", tree.error()); 101 } 102 103 TEST(AXTreeTest, LeaveOrphanedNewChildFails) { 104 AXTreeUpdate initial_state; 105 initial_state.nodes.resize(1); 106 initial_state.nodes[0].id = 1; 107 initial_state.nodes[0].role = AX_ROLE_ROOT_WEB_AREA; 108 AXTree tree(initial_state); 109 110 // This should fail because we add a new child to the root node 111 // but never update it. 112 AXTreeUpdate update; 113 update.nodes.resize(1); 114 update.nodes[0].id = 1; 115 update.nodes[0].role = AX_ROLE_ROOT_WEB_AREA; 116 update.nodes[0].child_ids.push_back(2); 117 EXPECT_FALSE(tree.Unserialize(update)); 118 ASSERT_EQ("Nodes left pending by the update: 2", tree.error()); 119 } 120 121 TEST(AXTreeTest, DuplicateChildIdFails) { 122 AXTreeUpdate initial_state; 123 initial_state.nodes.resize(1); 124 initial_state.nodes[0].id = 1; 125 initial_state.nodes[0].role = AX_ROLE_ROOT_WEB_AREA; 126 AXTree tree(initial_state); 127 128 // This should fail because a child id appears twice. 129 AXTreeUpdate update; 130 update.nodes.resize(2); 131 update.nodes[0].id = 1; 132 update.nodes[0].role = AX_ROLE_ROOT_WEB_AREA; 133 update.nodes[0].child_ids.push_back(2); 134 update.nodes[0].child_ids.push_back(2); 135 update.nodes[1].id = 2; 136 EXPECT_FALSE(tree.Unserialize(update)); 137 ASSERT_EQ("Node 1 has duplicate child id 2", tree.error()); 138 } 139 140 TEST(AXTreeTest, InvalidReparentingFails) { 141 AXTreeUpdate initial_state; 142 initial_state.nodes.resize(3); 143 initial_state.nodes[0].id = 1; 144 initial_state.nodes[0].role = AX_ROLE_ROOT_WEB_AREA; 145 initial_state.nodes[0].child_ids.push_back(2); 146 initial_state.nodes[1].id = 2; 147 initial_state.nodes[1].child_ids.push_back(3); 148 initial_state.nodes[2].id = 3; 149 150 AXTree tree(initial_state); 151 152 // This should fail because node 3 is reparented from node 2 to node 1 153 // without deleting node 1's subtree first. 154 AXTreeUpdate update; 155 update.nodes.resize(3); 156 update.nodes[0].id = 1; 157 update.nodes[0].role = AX_ROLE_ROOT_WEB_AREA; 158 update.nodes[0].child_ids.push_back(3); 159 update.nodes[0].child_ids.push_back(2); 160 update.nodes[1].id = 2; 161 update.nodes[2].id = 3; 162 EXPECT_FALSE(tree.Unserialize(update)); 163 ASSERT_EQ("Node 3 reparented from 2 to 1", tree.error()); 164 } 165 166 } // namespace ui 167