• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "icing/schema/joinable-property-manager.h"
16 
17 #include <cstdint>
18 #include <memory>
19 #include <string>
20 #include <string_view>
21 #include <vector>
22 
23 #include "icing/text_classifier/lib3/utils/base/status.h"
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 #include "icing/document-builder.h"
27 #include "icing/file/filesystem.h"
28 #include "icing/proto/document.pb.h"
29 #include "icing/proto/schema.pb.h"
30 #include "icing/schema-builder.h"
31 #include "icing/schema/joinable-property.h"
32 #include "icing/schema/schema-type-manager.h"
33 #include "icing/schema/schema-util.h"
34 #include "icing/store/dynamic-trie-key-mapper.h"
35 #include "icing/store/key-mapper.h"
36 #include "icing/testing/common-matchers.h"
37 #include "icing/testing/tmp-directory.h"
38 
39 namespace icing {
40 namespace lib {
41 
42 namespace {
43 
44 using ::testing::ElementsAre;
45 using ::testing::IsNull;
46 using ::testing::Pointee;
47 using ::testing::SizeIs;
48 
49 // type and property names of Email
50 static constexpr char kTypeEmail[] = "Email";
51 // joinable
52 static constexpr char kPropertyReceiverQualifiedId[] = "receiverQualifiedId";
53 static constexpr char kPropertySenderQualifiedId[] = "senderQualifiedId";
54 // non-joinable
55 static constexpr char kPropertyAttachment[] = "attachment";
56 static constexpr char kPropertySubject[] = "subject";
57 static constexpr char kPropertyText[] = "text";
58 static constexpr char kPropertyTimestamp[] = "timestamp";
59 
60 // type and property names of Conversation
61 static constexpr char kTypeConversation[] = "Conversation";
62 // joinable
63 static constexpr char kPropertyEmails[] = "emails";
64 static constexpr char kPropertyGroupQualifiedId[] = "groupQualifiedId";
65 // non-joinable
66 static constexpr char kPropertyName[] = "name";
67 static constexpr char kPropertyNumber[] = "number";
68 
69 constexpr int64_t kDefaultTimestamp = 1663274901;
70 
CreateSenderQualifiedIdPropertyConfig()71 PropertyConfigProto CreateSenderQualifiedIdPropertyConfig() {
72   return PropertyConfigBuilder()
73       .SetName(kPropertySenderQualifiedId)
74       .SetDataTypeString(TERM_MATCH_PREFIX, TOKENIZER_PLAIN)
75       .SetJoinable(JOINABLE_VALUE_TYPE_QUALIFIED_ID, /*propagate_delete=*/true)
76       .SetCardinality(CARDINALITY_OPTIONAL)
77       .Build();
78 }
79 
CreateReceiverQualifiedIdPropertyConfig()80 PropertyConfigProto CreateReceiverQualifiedIdPropertyConfig() {
81   return PropertyConfigBuilder()
82       .SetName(kPropertyReceiverQualifiedId)
83       .SetDataTypeString(TERM_MATCH_PREFIX, TOKENIZER_PLAIN)
84       .SetJoinable(JOINABLE_VALUE_TYPE_QUALIFIED_ID, /*propagate_delete=*/true)
85       .SetCardinality(CARDINALITY_OPTIONAL)
86       .Build();
87 }
88 
CreateGroupQualifiedIdPropertyConfig()89 PropertyConfigProto CreateGroupQualifiedIdPropertyConfig() {
90   return PropertyConfigBuilder()
91       .SetName(kPropertyGroupQualifiedId)
92       .SetDataTypeString(TERM_MATCH_PREFIX, TOKENIZER_PLAIN)
93       .SetJoinable(JOINABLE_VALUE_TYPE_QUALIFIED_ID, /*propagate_delete=*/false)
94       .SetCardinality(CARDINALITY_OPTIONAL)
95       .Build();
96 }
97 
CreateEmailTypeConfig()98 SchemaTypeConfigProto CreateEmailTypeConfig() {
99   return SchemaTypeConfigBuilder()
100       .SetType(kTypeEmail)
101       .AddProperty(PropertyConfigBuilder()
102                        .SetName(kPropertySubject)
103                        .SetDataTypeString(TERM_MATCH_EXACT, TOKENIZER_PLAIN)
104                        .SetCardinality(CARDINALITY_OPTIONAL))
105       .AddProperty(PropertyConfigBuilder()
106                        .SetName(kPropertyText)
107                        .SetDataTypeString(TERM_MATCH_UNKNOWN, TOKENIZER_NONE)
108                        .SetCardinality(CARDINALITY_OPTIONAL))
109       .AddProperty(PropertyConfigBuilder()
110                        .SetName(kPropertyAttachment)
111                        .SetDataType(TYPE_BYTES)
112                        .SetCardinality(CARDINALITY_OPTIONAL))
113       .AddProperty(PropertyConfigBuilder()
114                        .SetName(kPropertyTimestamp)
115                        .SetDataType(TYPE_INT64)
116                        .SetCardinality(CARDINALITY_OPTIONAL))
117       .AddProperty(CreateSenderQualifiedIdPropertyConfig())
118       .AddProperty(CreateReceiverQualifiedIdPropertyConfig())
119       .Build();
120 }
121 
CreateConversationTypeConfig()122 SchemaTypeConfigProto CreateConversationTypeConfig() {
123   return SchemaTypeConfigBuilder()
124       .SetType(kTypeConversation)
125       .AddProperty(PropertyConfigBuilder()
126                        .SetName(kPropertyName)
127                        .SetDataTypeString(TERM_MATCH_EXACT, TOKENIZER_PLAIN)
128                        .SetCardinality(CARDINALITY_OPTIONAL))
129       .AddProperty(PropertyConfigBuilder()
130                        .SetName(kPropertyNumber)
131                        .SetDataType(TYPE_INT64)
132                        .SetCardinality(CARDINALITY_OPTIONAL))
133       .AddProperty(CreateGroupQualifiedIdPropertyConfig())
134       .AddProperty(
135           PropertyConfigBuilder()
136               .SetName(kPropertyEmails)
137               .SetDataTypeDocument(kTypeEmail, /*index_nested_properties=*/true)
138               .SetCardinality(CARDINALITY_OPTIONAL))
139       .Build();
140 }
141 
142 class JoinablePropertyManagerTest : public ::testing::Test {
143  protected:
SetUp()144   void SetUp() override {
145     test_dir_ = GetTestTempDir() + "/icing";
146 
147     type_config_map_.emplace(kTypeEmail, CreateEmailTypeConfig());
148     type_config_map_.emplace(kTypeConversation, CreateConversationTypeConfig());
149 
150     email_document_ =
151         DocumentBuilder()
152             .SetKey("icing", "email/1")
153             .SetSchema(kTypeEmail)
154             .AddStringProperty(kPropertySubject, "the subject")
155             .AddStringProperty(kPropertyText, "the text")
156             .AddStringProperty(kPropertySenderQualifiedId, "pkg$db/ns#Person1")
157             .AddStringProperty(kPropertyReceiverQualifiedId,
158                                "pkg$db/ns#Person2")
159             .AddBytesProperty(kPropertyAttachment, "attachment")
160             .AddInt64Property(kPropertyTimestamp, kDefaultTimestamp)
161             .Build();
162 
163     conversation_document_ =
164         DocumentBuilder()
165             .SetKey("icing", "conversation/1")
166             .SetSchema(kTypeConversation)
167             .AddStringProperty(kPropertyName, "the conversation")
168             .AddInt64Property(kPropertyNumber, 2)
169             .AddDocumentProperty(kPropertyEmails,
170                                  DocumentProto(email_document_))
171             .AddStringProperty(kPropertyGroupQualifiedId,
172                                "pkg$db/ns#GroupQualifiedId1")
173             .Build();
174 
175     // DynamicTrieKeyMapper uses 3 internal arrays for bookkeeping. Give each
176     // one 128KiB so the total DynamicTrieKeyMapper should get 384KiB
177     int key_mapper_size = 3 * 128 * 1024;
178     ICING_ASSERT_OK_AND_ASSIGN(schema_type_mapper_,
179                                DynamicTrieKeyMapper<SchemaTypeId>::Create(
180                                    filesystem_, test_dir_, key_mapper_size));
181     ICING_ASSERT_OK(schema_type_mapper_->Put(kTypeEmail, 0));
182     ICING_ASSERT_OK(schema_type_mapper_->Put(kTypeConversation, 1));
183   }
184 
TearDown()185   void TearDown() override {
186     schema_type_mapper_.reset();
187     filesystem_.DeleteDirectoryRecursively(test_dir_.c_str());
188   }
189 
190   Filesystem filesystem_;
191   std::string test_dir_;
192   SchemaUtil::TypeConfigMap type_config_map_;
193   std::unique_ptr<KeyMapper<SchemaTypeId>> schema_type_mapper_;
194 
195   DocumentProto email_document_;
196   DocumentProto conversation_document_;
197 };
198 
TEST_F(JoinablePropertyManagerTest,ExtractJoinableProperties)199 TEST_F(JoinablePropertyManagerTest, ExtractJoinableProperties) {
200   // Use SchemaTypeManager factory method to instantiate
201   // JoinablePropertyManager.
202   ICING_ASSERT_OK_AND_ASSIGN(
203       std::unique_ptr<SchemaTypeManager> schema_type_manager,
204       SchemaTypeManager::Create(type_config_map_, schema_type_mapper_.get()));
205 
206   // Extracts all joinable properties from 'Email' document
207   ICING_ASSERT_OK_AND_ASSIGN(JoinablePropertyGroup joinable_property_group,
208                              schema_type_manager->joinable_property_manager()
209                                  .ExtractJoinableProperties(email_document_));
210 
211   // Qualified Id joinable properties
212   EXPECT_THAT(joinable_property_group.qualified_id_properties, SizeIs(2));
213 
214   EXPECT_THAT(
215       joinable_property_group.qualified_id_properties[0].metadata,
216       EqualsJoinablePropertyMetadata(
217           /*expected_id=*/0, /*expected_property_path=*/"receiverQualifiedId",
218           CreateReceiverQualifiedIdPropertyConfig()));
219   EXPECT_THAT(joinable_property_group.qualified_id_properties[0].values,
220               ElementsAre("pkg$db/ns#Person2"));
221 
222   EXPECT_THAT(
223       joinable_property_group.qualified_id_properties[1].metadata,
224       EqualsJoinablePropertyMetadata(
225           /*expected_id=*/1, /*expected_property_path=*/"senderQualifiedId",
226           CreateSenderQualifiedIdPropertyConfig()));
227   EXPECT_THAT(joinable_property_group.qualified_id_properties[1].values,
228               ElementsAre("pkg$db/ns#Person1"));
229 }
230 
TEST_F(JoinablePropertyManagerTest,ExtractJoinablePropertiesNested)231 TEST_F(JoinablePropertyManagerTest, ExtractJoinablePropertiesNested) {
232   // Use SchemaTypeManager factory method to instantiate
233   // JoinablePropertyManager.
234   ICING_ASSERT_OK_AND_ASSIGN(
235       std::unique_ptr<SchemaTypeManager> schema_type_manager,
236       SchemaTypeManager::Create(type_config_map_, schema_type_mapper_.get()));
237 
238   // Extracts all joinable properties from 'Conversation' document
239   ICING_ASSERT_OK_AND_ASSIGN(
240       JoinablePropertyGroup joinable_property_group,
241       schema_type_manager->joinable_property_manager()
242           .ExtractJoinableProperties(conversation_document_));
243 
244   // Qualified Id joinable properties
245   EXPECT_THAT(joinable_property_group.qualified_id_properties, SizeIs(3));
246 
247   EXPECT_THAT(joinable_property_group.qualified_id_properties[0].metadata,
248               EqualsJoinablePropertyMetadata(
249                   /*expected_id=*/0,
250                   /*expected_property_path=*/"emails.receiverQualifiedId",
251                   CreateReceiverQualifiedIdPropertyConfig()));
252   EXPECT_THAT(joinable_property_group.qualified_id_properties[0].values,
253               ElementsAre("pkg$db/ns#Person2"));
254 
255   EXPECT_THAT(joinable_property_group.qualified_id_properties[1].metadata,
256               EqualsJoinablePropertyMetadata(
257                   /*expected_id=*/1,
258                   /*expected_property_path=*/"emails.senderQualifiedId",
259                   CreateSenderQualifiedIdPropertyConfig()));
260   EXPECT_THAT(joinable_property_group.qualified_id_properties[1].values,
261               ElementsAre("pkg$db/ns#Person1"));
262 
263   EXPECT_THAT(
264       joinable_property_group.qualified_id_properties[2].metadata,
265       EqualsJoinablePropertyMetadata(
266           /*expected_id=*/2, /*expected_property_path=*/"groupQualifiedId",
267           CreateGroupQualifiedIdPropertyConfig()));
268   EXPECT_THAT(joinable_property_group.qualified_id_properties[2].values,
269               ElementsAre("pkg$db/ns#GroupQualifiedId1"));
270 }
271 
TEST_F(JoinablePropertyManagerTest,ExtractJoinablePropertiesShouldIgnoreEmptyContents)272 TEST_F(JoinablePropertyManagerTest,
273        ExtractJoinablePropertiesShouldIgnoreEmptyContents) {
274   // Use SchemaTypeManager factory method to instantiate
275   // JoinablePropertyManager.
276   ICING_ASSERT_OK_AND_ASSIGN(
277       std::unique_ptr<SchemaTypeManager> schema_type_manager,
278       SchemaTypeManager::Create(type_config_map_, schema_type_mapper_.get()));
279 
280   // Create an email document without receiverQualifiedId.
281   DocumentProto another_email_document =
282       DocumentBuilder()
283           .SetKey("icing", "email/2")
284           .SetSchema(kTypeEmail)
285           .AddStringProperty(kPropertySubject, "the subject")
286           .AddStringProperty(kPropertyText, "the text")
287           .AddBytesProperty(kPropertyAttachment, "attachment")
288           .AddStringProperty(kPropertySenderQualifiedId, "pkg$db/ns#Person1")
289           .AddInt64Property(kPropertyTimestamp, kDefaultTimestamp)
290           .Build();
291 
292   ICING_ASSERT_OK_AND_ASSIGN(
293       JoinablePropertyGroup joinable_property_group,
294       schema_type_manager->joinable_property_manager()
295           .ExtractJoinableProperties(another_email_document));
296 
297   // ExtractJoinableProperties should ignore receiverQualifiedId and not append
298   // a JoinableProperty instance of it into the vector.
299   EXPECT_THAT(joinable_property_group.qualified_id_properties, SizeIs(1));
300   EXPECT_THAT(
301       joinable_property_group.qualified_id_properties[0].metadata,
302       EqualsJoinablePropertyMetadata(
303           /*expected_id=*/1, /*expected_property_path=*/"senderQualifiedId",
304           CreateSenderQualifiedIdPropertyConfig()));
305   EXPECT_THAT(joinable_property_group.qualified_id_properties[0].values,
306               ElementsAre("pkg$db/ns#Person1"));
307 }
308 
TEST_F(JoinablePropertyManagerTest,GetJoinablePropertyMetadata)309 TEST_F(JoinablePropertyManagerTest, GetJoinablePropertyMetadata) {
310   // Use SchemaTypeManager factory method to instantiate
311   // JoinablePropertyManager.
312   ICING_ASSERT_OK_AND_ASSIGN(
313       std::unique_ptr<SchemaTypeManager> schema_type_manager,
314       SchemaTypeManager::Create(type_config_map_, schema_type_mapper_.get()));
315 
316   // Email (joinable property id -> joinable property path):
317   //   0 -> receiverQualifiedId
318   //   1 -> senderQualifiedId
319   EXPECT_THAT(
320       schema_type_manager->joinable_property_manager()
321           .GetJoinablePropertyMetadata(/*schema_type_id=*/0,
322                                        /*joinable_property_id=*/0),
323       IsOkAndHolds(Pointee(EqualsJoinablePropertyMetadata(
324           /*expected_id=*/0, /*expected_property_path=*/"receiverQualifiedId",
325           CreateReceiverQualifiedIdPropertyConfig()))));
326   EXPECT_THAT(
327       schema_type_manager->joinable_property_manager()
328           .GetJoinablePropertyMetadata(/*schema_type_id=*/0,
329                                        /*joinable_property_id=*/1),
330       IsOkAndHolds(Pointee(EqualsJoinablePropertyMetadata(
331           /*expected_id=*/1, /*expected_property_path=*/"senderQualifiedId",
332           CreateSenderQualifiedIdPropertyConfig()))));
333 
334   // Conversation (joinable property id -> joinable property path):
335   //   0 -> emails.receiverQualifiedId
336   //   1 -> emails.senderQualifiedId
337   //   2 -> groupQualifiedId
338   EXPECT_THAT(schema_type_manager->joinable_property_manager()
339                   .GetJoinablePropertyMetadata(/*schema_type_id=*/1,
340                                                /*joinable_property_id=*/0),
341               IsOkAndHolds(Pointee(EqualsJoinablePropertyMetadata(
342                   /*expected_id=*/0,
343                   /*expected_property_path=*/"emails.receiverQualifiedId",
344                   CreateReceiverQualifiedIdPropertyConfig()))));
345   EXPECT_THAT(schema_type_manager->joinable_property_manager()
346                   .GetJoinablePropertyMetadata(/*schema_type_id=*/1,
347                                                /*joinable_property_id=*/1),
348               IsOkAndHolds(Pointee(EqualsJoinablePropertyMetadata(
349                   /*expected_id=*/1,
350                   /*expected_property_path=*/"emails.senderQualifiedId",
351                   CreateSenderQualifiedIdPropertyConfig()))));
352   EXPECT_THAT(
353       schema_type_manager->joinable_property_manager()
354           .GetJoinablePropertyMetadata(/*schema_type_id=*/1,
355                                        /*joinable_property_id=*/2),
356       IsOkAndHolds(Pointee(EqualsJoinablePropertyMetadata(
357           /*expected_id=*/2, /*expected_property_path=*/"groupQualifiedId",
358           CreateGroupQualifiedIdPropertyConfig()))));
359 }
360 
TEST_F(JoinablePropertyManagerTest,GetJoinablePropertyMetadataInvalidSchemaTypeId)361 TEST_F(JoinablePropertyManagerTest,
362        GetJoinablePropertyMetadataInvalidSchemaTypeId) {
363   // Use SchemaTypeManager factory method to instantiate
364   // JoinablePropertyManager.
365   ICING_ASSERT_OK_AND_ASSIGN(
366       std::unique_ptr<SchemaTypeManager> schema_type_manager,
367       SchemaTypeManager::Create(type_config_map_, schema_type_mapper_.get()));
368   ASSERT_THAT(type_config_map_, SizeIs(2));
369 
370   EXPECT_THAT(schema_type_manager->joinable_property_manager()
371                   .GetJoinablePropertyMetadata(/*schema_type_id=*/-1,
372                                                /*joinable_property_id=*/0),
373               StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
374   EXPECT_THAT(schema_type_manager->joinable_property_manager()
375                   .GetJoinablePropertyMetadata(/*schema_type_id=*/2,
376                                                /*joinable_property_id=*/0),
377               StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
378 }
379 
TEST_F(JoinablePropertyManagerTest,GetJoinablePropertyMetadataInvalidJoinablePropertyId)380 TEST_F(JoinablePropertyManagerTest,
381        GetJoinablePropertyMetadataInvalidJoinablePropertyId) {
382   // Use SchemaTypeManager factory method to instantiate
383   // JoinablePropertyManager.
384   ICING_ASSERT_OK_AND_ASSIGN(
385       std::unique_ptr<SchemaTypeManager> schema_type_manager,
386       SchemaTypeManager::Create(type_config_map_, schema_type_mapper_.get()));
387 
388   // Email (joinable property id -> joinable property path):
389   //   0 -> receiverQualifiedId
390   //   1 -> senderQualifiedId
391   EXPECT_THAT(schema_type_manager->joinable_property_manager()
392                   .GetJoinablePropertyMetadata(/*schema_type_id=*/0,
393                                                /*joinable_property_id=*/-1),
394               StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
395   EXPECT_THAT(schema_type_manager->joinable_property_manager()
396                   .GetJoinablePropertyMetadata(/*schema_type_id=*/0,
397                                                /*joinable_property_id=*/2),
398               StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
399 
400   // Conversation (joinable property id -> joinable property path):
401   //   0 -> emails.receiverQualifiedId
402   //   1 -> emails.senderQualifiedId
403   //   2 -> groupQualifiedId
404   EXPECT_THAT(schema_type_manager->joinable_property_manager()
405                   .GetJoinablePropertyMetadata(/*schema_type_id=*/1,
406                                                /*joinable_property_id=*/-1),
407               StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
408   EXPECT_THAT(schema_type_manager->joinable_property_manager()
409                   .GetJoinablePropertyMetadata(/*schema_type_id=*/1,
410                                                /*joinable_property_id=*/3),
411               StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
412 }
413 
TEST_F(JoinablePropertyManagerTest,GetJoinablePropertyMetadataByPath)414 TEST_F(JoinablePropertyManagerTest, GetJoinablePropertyMetadataByPath) {
415   // Use SchemaTypeManager factory method to instantiate
416   // JoinablePropertyManager.
417   ICING_ASSERT_OK_AND_ASSIGN(
418       std::unique_ptr<SchemaTypeManager> schema_type_manager,
419       SchemaTypeManager::Create(type_config_map_, schema_type_mapper_.get()));
420 
421   // Email (joinable property id -> joinable property path):
422   //   0 -> receiverQualifiedId
423   //   1 -> senderQualifiedId
424   EXPECT_THAT(
425       schema_type_manager->joinable_property_manager()
426           .GetJoinablePropertyMetadata(/*schema_type_id=*/0,
427                                        "receiverQualifiedId"),
428       IsOkAndHolds(Pointee(EqualsJoinablePropertyMetadata(
429           /*expected_id=*/0, /*expected_property_path=*/"receiverQualifiedId",
430           CreateReceiverQualifiedIdPropertyConfig()))));
431   EXPECT_THAT(
432       schema_type_manager->joinable_property_manager()
433           .GetJoinablePropertyMetadata(/*schema_type_id=*/0,
434                                        "senderQualifiedId"),
435       IsOkAndHolds(Pointee(EqualsJoinablePropertyMetadata(
436           /*expected_id=*/1, /*expected_property_path=*/"senderQualifiedId",
437           CreateSenderQualifiedIdPropertyConfig()))));
438 
439   // Conversation (joinable property id -> joinable property path):
440   //   0 -> emails.receiverQualifiedId
441   //   1 -> emails.senderQualifiedId
442   //   2 -> groupQualifiedId
443   EXPECT_THAT(schema_type_manager->joinable_property_manager()
444                   .GetJoinablePropertyMetadata(/*schema_type_id=*/1,
445                                                "emails.receiverQualifiedId"),
446               IsOkAndHolds(Pointee(EqualsJoinablePropertyMetadata(
447                   /*expected_id=*/0,
448                   /*expected_property_path=*/"emails.receiverQualifiedId",
449                   CreateReceiverQualifiedIdPropertyConfig()))));
450   EXPECT_THAT(schema_type_manager->joinable_property_manager()
451                   .GetJoinablePropertyMetadata(/*schema_type_id=*/1,
452                                                "emails.senderQualifiedId"),
453               IsOkAndHolds(Pointee(EqualsJoinablePropertyMetadata(
454                   /*expected_id=*/1,
455                   /*expected_property_path=*/"emails.senderQualifiedId",
456                   CreateSenderQualifiedIdPropertyConfig()))));
457   EXPECT_THAT(
458       schema_type_manager->joinable_property_manager()
459           .GetJoinablePropertyMetadata(/*schema_type_id=*/1,
460                                        "groupQualifiedId"),
461       IsOkAndHolds(Pointee(EqualsJoinablePropertyMetadata(
462           /*expected_id=*/2, /*expected_property_path=*/"groupQualifiedId",
463           CreateGroupQualifiedIdPropertyConfig()))));
464 }
465 
TEST_F(JoinablePropertyManagerTest,GetJoinablePropertyMetadataByPathInvalidSchemaTypeId)466 TEST_F(JoinablePropertyManagerTest,
467        GetJoinablePropertyMetadataByPathInvalidSchemaTypeId) {
468   // Use SchemaTypeManager factory method to instantiate
469   // JoinablePropertyManager.
470   ICING_ASSERT_OK_AND_ASSIGN(
471       std::unique_ptr<SchemaTypeManager> schema_type_manager,
472       SchemaTypeManager::Create(type_config_map_, schema_type_mapper_.get()));
473   ASSERT_THAT(type_config_map_, SizeIs(2));
474 
475   EXPECT_THAT(schema_type_manager->joinable_property_manager()
476                   .GetJoinablePropertyMetadata(/*schema_type_id=*/-1,
477                                                "receiverQualifiedId"),
478               StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
479   EXPECT_THAT(schema_type_manager->joinable_property_manager()
480                   .GetJoinablePropertyMetadata(/*schema_type_id=*/2,
481                                                "receiverQualifiedId"),
482               StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
483 }
484 
TEST_F(JoinablePropertyManagerTest,GetJoinablePropertyMetadataByPathNotExist)485 TEST_F(JoinablePropertyManagerTest, GetJoinablePropertyMetadataByPathNotExist) {
486   // Use SchemaTypeManager factory method to instantiate
487   // JoinablePropertyManager.
488   ICING_ASSERT_OK_AND_ASSIGN(
489       std::unique_ptr<SchemaTypeManager> schema_type_manager,
490       SchemaTypeManager::Create(type_config_map_, schema_type_mapper_.get()));
491 
492   EXPECT_THAT(
493       schema_type_manager->joinable_property_manager()
494           .GetJoinablePropertyMetadata(/*schema_type_id=*/0, "nonExistingPath"),
495       IsOkAndHolds(IsNull()));
496   EXPECT_THAT(schema_type_manager->joinable_property_manager()
497                   .GetJoinablePropertyMetadata(/*schema_type_id=*/1,
498                                                "emails.nonExistingPath"),
499               IsOkAndHolds(IsNull()));
500 }
501 
502 // Note: valid GetMetadataList has been tested in
503 // JoinablePropertyManagerBuildTest.
TEST_F(JoinablePropertyManagerTest,GetMetadataListInvalidSchemaTypeName)504 TEST_F(JoinablePropertyManagerTest, GetMetadataListInvalidSchemaTypeName) {
505   // Use SchemaTypeManager factory method to instantiate
506   // JoinablePropertyManager.
507   ICING_ASSERT_OK_AND_ASSIGN(
508       std::unique_ptr<SchemaTypeManager> schema_type_manager,
509       SchemaTypeManager::Create(type_config_map_, schema_type_mapper_.get()));
510 
511   EXPECT_THAT(schema_type_manager->joinable_property_manager().GetMetadataList(
512                   "NonExistingSchemaTypeName"),
513               StatusIs(libtextclassifier3::StatusCode::NOT_FOUND));
514 }
515 
516 }  // namespace
517 
518 }  // namespace lib
519 }  // namespace icing
520