diff options
Diffstat (limited to 'icing/scoring/advanced_scoring/advanced-scorer_test.cc')
-rw-r--r-- | icing/scoring/advanced_scoring/advanced-scorer_test.cc | 208 |
1 files changed, 206 insertions, 2 deletions
diff --git a/icing/scoring/advanced_scoring/advanced-scorer_test.cc b/icing/scoring/advanced_scoring/advanced-scorer_test.cc index b3a47ba..c962bc5 100644 --- a/icing/scoring/advanced_scoring/advanced-scorer_test.cc +++ b/icing/scoring/advanced_scoring/advanced-scorer_test.cc @@ -65,7 +65,12 @@ class AdvancedScorerTest : public testing::Test { ICING_ASSERT_OK_AND_ASSIGN( DocumentStore::CreateResult create_result, DocumentStore::Create(&filesystem_, doc_store_dir_, &fake_clock_, - schema_store_.get())); + schema_store_.get(), + /*force_recovery_and_revalidate_documents=*/false, + /*namespace_id_fingerprint=*/false, + PortableFileBackedProtoLog< + DocumentWrapper>::kDeflateCompressionLevel, + /*initialize_stats=*/nullptr)); document_store_ = std::move(create_result.document_store); // Creates a simple email schema @@ -77,8 +82,31 @@ class AdvancedScorerTest : public testing::Test { .SetDataTypeString( TermMatchType::PREFIX, StringIndexingConfig::TokenizerType::PLAIN) - .SetDataType(TYPE_STRING) .SetCardinality(CARDINALITY_OPTIONAL))) + .AddType(SchemaTypeConfigBuilder() + .SetType("person") + .AddProperty( + PropertyConfigBuilder() + .SetName("emailAddress") + .SetDataTypeString( + TermMatchType::PREFIX, + StringIndexingConfig::TokenizerType::PLAIN) + .SetCardinality(CARDINALITY_OPTIONAL)) + .AddProperty( + PropertyConfigBuilder() + .SetName("name") + .SetDataTypeString( + TermMatchType::PREFIX, + StringIndexingConfig::TokenizerType::PLAIN) + .SetCardinality(CARDINALITY_OPTIONAL)) + + .AddProperty( + PropertyConfigBuilder() + .SetName("phoneNumber") + .SetDataTypeString( + TermMatchType::PREFIX, + StringIndexingConfig::TokenizerType::PLAIN) + .SetCardinality(CARDINALITY_OPTIONAL))) .Build(); ICING_ASSERT_OK(schema_store_->SetSchema(test_email_schema)); @@ -135,6 +163,27 @@ ScoringSpecProto CreateAdvancedScoringSpec( return scoring_spec; } +PropertyWeight CreatePropertyWeight(std::string path, double weight) { + PropertyWeight property_weight; + property_weight.set_path(std::move(path)); + property_weight.set_weight(weight); + return property_weight; +} + +TypePropertyWeights CreateTypePropertyWeights( + std::string schema_type, std::vector<PropertyWeight>&& property_weights) { + TypePropertyWeights type_property_weights; + type_property_weights.set_schema_type(std::move(schema_type)); + type_property_weights.mutable_property_weights()->Reserve( + property_weights.size()); + + for (PropertyWeight& property_weight : property_weights) { + *type_property_weights.add_property_weights() = std::move(property_weight); + } + + return type_property_weights; +} + TEST_F(AdvancedScorerTest, InvalidAdvancedScoringSpec) { // Empty scoring expression for advanced scoring ScoringSpecProto scoring_spec; @@ -541,6 +590,161 @@ TEST_F(AdvancedScorerTest, ChildrenScoresFunctionScoreExpression) { Eq(default_score)); } +TEST_F(AdvancedScorerTest, PropertyWeightsFunctionScoreExpression) { + DocumentProto test_document_1 = + DocumentBuilder().SetKey("namespace", "uri1").SetSchema("email").Build(); + DocumentProto test_document_2 = + DocumentBuilder().SetKey("namespace", "uri2").SetSchema("person").Build(); + DocumentProto test_document_3 = + DocumentBuilder().SetKey("namespace", "uri3").SetSchema("person").Build(); + + ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id_1, + document_store_->Put(test_document_1)); + ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id_2, + document_store_->Put(test_document_2)); + ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id_3, + document_store_->Put(test_document_3)); + + ScoringSpecProto spec_proto = CreateAdvancedScoringSpec(""); + + *spec_proto.add_type_property_weights() = CreateTypePropertyWeights( + /*schema_type=*/"email", + {CreatePropertyWeight(/*path=*/"subject", /*weight=*/1.0)}); + *spec_proto.add_type_property_weights() = CreateTypePropertyWeights( + /*schema_type=*/"person", + {CreatePropertyWeight(/*path=*/"emailAddress", /*weight=*/0.5), + CreatePropertyWeight(/*path=*/"name", /*weight=*/0.8), + CreatePropertyWeight(/*path=*/"phoneNumber", /*weight=*/1.0)}); + + // Let the hit for test_document_1 match property "subject". + // So this.propertyWeights() for test_document_1 will return [1]. + DocHitInfo doc_hit_info_1 = DocHitInfo(document_id_1); + doc_hit_info_1.UpdateSection(0); + + // Let the hit for test_document_2 match properties "emailAddress" and "name". + // So this.propertyWeights() for test_document_2 will return [0.5, 0.8]. + DocHitInfo doc_hit_info_2 = DocHitInfo(document_id_2); + doc_hit_info_2.UpdateSection(0); + doc_hit_info_2.UpdateSection(1); + + // Let the hit for test_document_3 match properties "emailAddress", "name" and + // "phoneNumber". So this.propertyWeights() for test_document_3 will return + // [0.5, 0.8, 1]. + DocHitInfo doc_hit_info_3 = DocHitInfo(document_id_3); + doc_hit_info_3.UpdateSection(0); + doc_hit_info_3.UpdateSection(1); + doc_hit_info_3.UpdateSection(2); + + spec_proto.set_advanced_scoring_expression("min(this.propertyWeights())"); + ICING_ASSERT_OK_AND_ASSIGN( + std::unique_ptr<AdvancedScorer> scorer, + AdvancedScorer::Create(spec_proto, + /*default_score=*/10, document_store_.get(), + schema_store_.get())); + // min([1]) = 1 + EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1)); + // min([0.5, 0.8]) = 0.5 + EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(0.5)); + // min([0.5, 0.8, 1.0]) = 0.5 + EXPECT_THAT(scorer->GetScore(doc_hit_info_3, /*query_it=*/nullptr), Eq(0.5)); + + spec_proto.set_advanced_scoring_expression("max(this.propertyWeights())"); + ICING_ASSERT_OK_AND_ASSIGN( + scorer, + AdvancedScorer::Create(spec_proto, + /*default_score=*/10, document_store_.get(), + schema_store_.get())); + // max([1]) = 1 + EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1)); + // max([0.5, 0.8]) = 0.8 + EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(0.8)); + // max([0.5, 0.8, 1.0]) = 1 + EXPECT_THAT(scorer->GetScore(doc_hit_info_3, /*query_it=*/nullptr), Eq(1)); + + spec_proto.set_advanced_scoring_expression("sum(this.propertyWeights())"); + ICING_ASSERT_OK_AND_ASSIGN( + scorer, + AdvancedScorer::Create(spec_proto, + /*default_score=*/10, document_store_.get(), + schema_store_.get())); + // sum([1]) = 1 + EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1)); + // sum([0.5, 0.8]) = 1.3 + EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(1.3)); + // sum([0.5, 0.8, 1.0]) = 2.3 + EXPECT_THAT(scorer->GetScore(doc_hit_info_3, /*query_it=*/nullptr), Eq(2.3)); +} + +TEST_F(AdvancedScorerTest, + PropertyWeightsFunctionScoreExpressionUnspecifiedWeights) { + DocumentProto test_document_1 = + DocumentBuilder().SetKey("namespace", "uri1").SetSchema("email").Build(); + DocumentProto test_document_2 = + DocumentBuilder().SetKey("namespace", "uri2").SetSchema("person").Build(); + + ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id_1, + document_store_->Put(test_document_1)); + ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id_2, + document_store_->Put(test_document_2)); + + ScoringSpecProto spec_proto = CreateAdvancedScoringSpec(""); + + // The entry for type "email" is missing, so every properties in "email" + // should get weight 1.0. + // The weight of "phoneNumber" in "person" type is unspecified, which should + // default to 1/2 = 0.5 + *spec_proto.add_type_property_weights() = CreateTypePropertyWeights( + /*schema_type=*/"person", + {CreatePropertyWeight(/*path=*/"emailAddress", /*weight=*/1.0), + CreatePropertyWeight(/*path=*/"name", /*weight=*/2)}); + + // Let the hit for test_document_1 match property "subject". + // So this.propertyWeights() for test_document_1 will return [1]. + DocHitInfo doc_hit_info_1 = DocHitInfo(document_id_1); + doc_hit_info_1.UpdateSection(0); + + // Let the hit for test_document_2 match properties "emailAddress", "name" and + // "phoneNumber". So this.propertyWeights() for test_document_3 will return + // [0.5, 1, 0.5]. + DocHitInfo doc_hit_info_2 = DocHitInfo(document_id_2); + doc_hit_info_2.UpdateSection(0); + doc_hit_info_2.UpdateSection(1); + doc_hit_info_2.UpdateSection(2); + + spec_proto.set_advanced_scoring_expression("min(this.propertyWeights())"); + ICING_ASSERT_OK_AND_ASSIGN( + std::unique_ptr<AdvancedScorer> scorer, + AdvancedScorer::Create(spec_proto, + /*default_score=*/10, document_store_.get(), + schema_store_.get())); + // min([1]) = 1 + EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1)); + // min([0.5, 1, 0.5]) = 0.5 + EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(0.5)); + + spec_proto.set_advanced_scoring_expression("max(this.propertyWeights())"); + ICING_ASSERT_OK_AND_ASSIGN( + scorer, + AdvancedScorer::Create(spec_proto, + /*default_score=*/10, document_store_.get(), + schema_store_.get())); + // max([1]) = 1 + EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1)); + // max([0.5, 1, 0.5]) = 1 + EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(1)); + + spec_proto.set_advanced_scoring_expression("sum(this.propertyWeights())"); + ICING_ASSERT_OK_AND_ASSIGN( + scorer, + AdvancedScorer::Create(spec_proto, + /*default_score=*/10, document_store_.get(), + schema_store_.get())); + // sum([1]) = 1 + EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1)); + // sum([0.5, 1, 0.5]) = 2 + EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(2)); +} + TEST_F(AdvancedScorerTest, InvalidChildrenScoresFunctionScoreExpression) { const double default_score = 123; |