summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Cherry2017-12-13 02:29:30 -0600
committerTom Cherry2017-12-13 18:58:33 -0600
commit26eba2879d7d7c9f51d14eba2484e25df15b8dd3 (patch)
tree590321ce07df0b330a4dee1e673f8c21dae6c93c /property_service
parent212257dbb9c877736d53cc3e786810fa7684861a (diff)
downloadplatform-system-core-26eba2879d7d7c9f51d14eba2484e25df15b8dd3.tar.gz
platform-system-core-26eba2879d7d7c9f51d14eba2484e25df15b8dd3.tar.xz
platform-system-core-26eba2879d7d7c9f51d14eba2484e25df15b8dd3.zip
Always check prefix matches array at each node
Currently, we only check if the name of a given node in the trie is a prefix match and the prefix matches array of the final node. This is incorrect however, as the prefix matches array of intermediate nodes may contain the prefix for a given property. This change adds that check and test cases for this case. Bug: 36001741 Test: new unit tests Change-Id: I9f58ebc559f2ac591aa44df9e71205704bf18f66
Diffstat (limited to 'property_service')
-rw-r--r--property_service/libpropertyinfoparser/include/property_info_parser/property_info_parser.h3
-rw-r--r--property_service/libpropertyinfoparser/property_info_parser.cpp33
-rw-r--r--property_service/libpropertyinfoserializer/property_info_serializer_test.cpp81
3 files changed, 105 insertions, 12 deletions
diff --git a/property_service/libpropertyinfoparser/include/property_info_parser/property_info_parser.h b/property_service/libpropertyinfoparser/include/property_info_parser/property_info_parser.h
index c2114ccff..8c3507e4f 100644
--- a/property_service/libpropertyinfoparser/include/property_info_parser/property_info_parser.h
+++ b/property_service/libpropertyinfoparser/include/property_info_parser/property_info_parser.h
@@ -172,6 +172,9 @@ class PropertyInfoArea : private SerializedData {
172 TrieNode root_node() const { return trie(header()->root_offset); } 172 TrieNode root_node() const { return trie(header()->root_offset); }
173 173
174 private: 174 private:
175 void CheckPrefixMatch(const char* remaining_name, const TrieNode& trie_node,
176 uint32_t* context_index, uint32_t* schema_index) const;
177
175 const PropertyInfoAreaHeader* header() const { 178 const PropertyInfoAreaHeader* header() const {
176 return reinterpret_cast<const PropertyInfoAreaHeader*>(data_base()); 179 return reinterpret_cast<const PropertyInfoAreaHeader*>(data_base());
177 } 180 }
diff --git a/property_service/libpropertyinfoparser/property_info_parser.cpp b/property_service/libpropertyinfoparser/property_info_parser.cpp
index 84f8c29f8..89864dd78 100644
--- a/property_service/libpropertyinfoparser/property_info_parser.cpp
+++ b/property_service/libpropertyinfoparser/property_info_parser.cpp
@@ -87,6 +87,21 @@ bool TrieNode::FindChildForString(const char* name, uint32_t namelen, TrieNode*
87 return true; 87 return true;
88} 88}
89 89
90void PropertyInfoArea::CheckPrefixMatch(const char* remaining_name, const TrieNode& trie_node,
91 uint32_t* context_index, uint32_t* schema_index) const {
92 const uint32_t remaining_name_size = strlen(remaining_name);
93 for (uint32_t i = 0; i < trie_node.num_prefixes(); ++i) {
94 auto prefix_len = trie_node.prefix(i)->namelen;
95 if (prefix_len > remaining_name_size) continue;
96
97 if (!strncmp(c_string(trie_node.prefix(i)->name_offset), remaining_name, prefix_len)) {
98 *context_index = trie_node.prefix(i)->context_index;
99 *schema_index = trie_node.prefix(i)->schema_index;
100 return;
101 }
102 }
103}
104
90void PropertyInfoArea::GetPropertyInfoIndexes(const char* name, uint32_t* context_index, 105void PropertyInfoArea::GetPropertyInfoIndexes(const char* name, uint32_t* context_index,
91 uint32_t* schema_index) const { 106 uint32_t* schema_index) const {
92 uint32_t return_context_index = ~0u; 107 uint32_t return_context_index = ~0u;
@@ -104,6 +119,10 @@ void PropertyInfoArea::GetPropertyInfoIndexes(const char* name, uint32_t* contex
104 return_schema_index = trie_node.schema_index(); 119 return_schema_index = trie_node.schema_index();
105 } 120 }
106 121
122 // Check prefixes at this node. This comes after the node check since these prefixes are by
123 // definition longer than the node itself.
124 CheckPrefixMatch(remaining_name, trie_node, &return_context_index, &return_schema_index);
125
107 if (sep == nullptr) { 126 if (sep == nullptr) {
108 break; 127 break;
109 } 128 }
@@ -128,18 +147,8 @@ void PropertyInfoArea::GetPropertyInfoIndexes(const char* name, uint32_t* contex
128 } 147 }
129 } 148 }
130 // Check prefix matches for prefixes not deliminated with '.' 149 // Check prefix matches for prefixes not deliminated with '.'
131 const uint32_t remaining_name_size = strlen(remaining_name); 150 CheckPrefixMatch(remaining_name, trie_node, &return_context_index, &return_schema_index);
132 for (uint32_t i = 0; i < trie_node.num_prefixes(); ++i) { 151 // Return previously found prefix match.
133 auto prefix_len = trie_node.prefix(i)->namelen;
134 if (prefix_len > remaining_name_size) continue;
135
136 if (!strncmp(c_string(trie_node.prefix(i)->name_offset), remaining_name, prefix_len)) {
137 if (context_index != nullptr) *context_index = trie_node.prefix(i)->context_index;
138 if (schema_index != nullptr) *schema_index = trie_node.prefix(i)->schema_index;
139 return;
140 }
141 }
142 // Return previously found '.' deliminated prefix match.
143 if (context_index != nullptr) *context_index = return_context_index; 152 if (context_index != nullptr) *context_index = return_context_index;
144 if (schema_index != nullptr) *schema_index = return_schema_index; 153 if (schema_index != nullptr) *schema_index = return_schema_index;
145 return; 154 return;
diff --git a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
index 5fa3463e1..b3fae268e 100644
--- a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
+++ b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
@@ -763,5 +763,86 @@ TEST(propertyinfoserializer, RealProperties) {
763 } 763 }
764} 764}
765 765
766TEST(propertyinfoserializer, GetPropertyInfo_prefix_without_dot) {
767 auto property_info = std::vector<PropertyInfoEntry>{
768 {"persist.radio", "1st", "1st", false},
769 {"persist.radio.something.else.here", "2nd", "2nd", false},
770 };
771
772 auto serialized_trie = std::string();
773 auto build_trie_error = std::string();
774 ASSERT_TRUE(BuildTrie(property_info, "default", "default", &serialized_trie, &build_trie_error))
775 << build_trie_error;
776
777 auto property_info_area = reinterpret_cast<const PropertyInfoArea*>(serialized_trie.data());
778
779 const char* context;
780 const char* schema;
781 property_info_area->GetPropertyInfo("persist.radio", &context, &schema);
782 EXPECT_STREQ("1st", context);
783 EXPECT_STREQ("1st", schema);
784 property_info_area->GetPropertyInfo("persist.radio.subproperty", &context, &schema);
785 EXPECT_STREQ("1st", context);
786 EXPECT_STREQ("1st", schema);
787 property_info_area->GetPropertyInfo("persist.radiowords", &context, &schema);
788 EXPECT_STREQ("1st", context);
789 EXPECT_STREQ("1st", schema);
790 property_info_area->GetPropertyInfo("persist.radio.long.long.long.sub.property", &context,
791 &schema);
792 EXPECT_STREQ("1st", context);
793 EXPECT_STREQ("1st", schema);
794 property_info_area->GetPropertyInfo("persist.radio.something.else.here", &context, &schema);
795 EXPECT_STREQ("2nd", context);
796 EXPECT_STREQ("2nd", schema);
797 property_info_area->GetPropertyInfo("persist.radio.something.else.here2", &context, &schema);
798 EXPECT_STREQ("2nd", context);
799 EXPECT_STREQ("2nd", schema);
800 property_info_area->GetPropertyInfo("persist.radio.something.else.here.after", &context, &schema);
801 EXPECT_STREQ("2nd", context);
802 EXPECT_STREQ("2nd", schema);
803 property_info_area->GetPropertyInfo("persist.radio.something.else.nothere", &context, &schema);
804 EXPECT_STREQ("1st", context);
805 EXPECT_STREQ("1st", schema);
806 property_info_area->GetPropertyInfo("persist.radio.something.else", &context, &schema);
807 EXPECT_STREQ("1st", context);
808 EXPECT_STREQ("1st", schema);
809}
810
811TEST(propertyinfoserializer, GetPropertyInfo_prefix_with_dot_vs_without) {
812 auto property_info = std::vector<PropertyInfoEntry>{
813 {"persist.", "1st", "1st", false},
814 {"persist.radio", "2nd", "2nd", false},
815 {"persist.radio.long.property.exact.match", "3rd", "3rd", true},
816 };
817
818 auto serialized_trie = std::string();
819 auto build_trie_error = std::string();
820 ASSERT_TRUE(BuildTrie(property_info, "default", "default", &serialized_trie, &build_trie_error))
821 << build_trie_error;
822
823 auto property_info_area = reinterpret_cast<const PropertyInfoArea*>(serialized_trie.data());
824
825 const char* context;
826 const char* schema;
827 property_info_area->GetPropertyInfo("persist.notradio", &context, &schema);
828 EXPECT_STREQ("1st", context);
829 EXPECT_STREQ("1st", schema);
830 property_info_area->GetPropertyInfo("persist.radio", &context, &schema);
831 EXPECT_STREQ("2nd", context);
832 EXPECT_STREQ("2nd", schema);
833 property_info_area->GetPropertyInfo("persist.radio.subproperty", &context, &schema);
834 EXPECT_STREQ("2nd", context);
835 EXPECT_STREQ("2nd", schema);
836 property_info_area->GetPropertyInfo("persist.radiowords", &context, &schema);
837 EXPECT_STREQ("2nd", context);
838 EXPECT_STREQ("2nd", schema);
839 property_info_area->GetPropertyInfo("persist.radio.long.property.prefix.match", &context, &schema);
840 EXPECT_STREQ("2nd", context);
841 EXPECT_STREQ("2nd", schema);
842 property_info_area->GetPropertyInfo("persist.radio.long.property.exact.match", &context, &schema);
843 EXPECT_STREQ("3rd", context);
844 EXPECT_STREQ("3rd", schema);
845}
846
766} // namespace properties 847} // namespace properties
767} // namespace android 848} // namespace android