blob: 1e1880f11273d072c361ea97fbdc9311a6e8c8ca [file] [log] [blame]
// Copyright (C) 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "icing/index/hit/doc-hit-info.h"
#include "icing/index/hit/hit.h"
#include "icing/schema/section.h"
#include "icing/store/document-id.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace icing {
namespace lib {
using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::IsTrue;
using ::testing::Ne;
constexpr DocumentId kSomeDocumentId = 12;
constexpr DocumentId kSomeOtherDocumentId = 54;
TEST(DocHitInfoTest, InitialMaxHitScores) {
DocHitInfo info(kSomeDocumentId);
for (SectionId i = 0; i <= kMaxSectionId; ++i) {
EXPECT_THAT(info.max_hit_score(i), Eq(Hit::kDefaultHitScore));
}
}
TEST(DocHitInfoTest, UpdateHitScores) {
DocHitInfo info(kSomeDocumentId);
ASSERT_THAT(info.max_hit_score(3), Eq(Hit::kDefaultHitScore));
// Updating a section for the first time, should change its max hit score,
// even though the hit score (16) may be lower than the current value returned
// by info.max_hit_score(3) (kDefaultHitScore)
info.UpdateSection(3, 16);
EXPECT_THAT(info.max_hit_score(3), Eq(16));
// Updating a section with a hit score lower than the previously set one
// should not update max hit score.
info.UpdateSection(3, 15);
EXPECT_THAT(info.max_hit_score(3), Eq(16));
// Updating a section with a hit score higher than the previously set one
// should update the max hit score.
info.UpdateSection(3, 17);
EXPECT_THAT(info.max_hit_score(3), Eq(17));
// Updating a section with kDefaultHitScore should *never* set the
// max_hit_score to kDefaultHitScore (unless it already was kDefaultHitScore)
// because kDefaultHitScore is the lowest possible valid hit score.
info.UpdateSection(3, Hit::kDefaultHitScore);
EXPECT_THAT(info.max_hit_score(3), Eq(17));
// Updating a section with kMaxHitScore should *always* set the max hit
// score to kMaxHitScore (regardless of what value kMaxHitScore is
// defined with).
info.UpdateSection(3, Hit::kMaxHitScore);
EXPECT_THAT(info.max_hit_score(3), Eq(Hit::kMaxHitScore));
// Updating a section that has had kMaxHitScore explicitly set, should
// *never* change the max hit score (regardless of what value kMaxHitScore
// is defined with).
info.UpdateSection(3, 16);
EXPECT_THAT(info.max_hit_score(3), Eq(Hit::kMaxHitScore));
}
TEST(DocHitInfoTest, UpdateSectionIdMask) {
DocHitInfo info(kSomeDocumentId);
EXPECT_THAT(info.hit_section_ids_mask(), Eq(kSectionIdMaskNone));
info.UpdateSection(3, 16);
EXPECT_THAT(info.hit_section_ids_mask() & 1U << 3, IsTrue());
// Calling update again shouldn't do anything
info.UpdateSection(3, 15);
EXPECT_THAT(info.hit_section_ids_mask() & 1U << 3, IsTrue());
// Updating another section shouldn't do anything
info.UpdateSection(2, 77);
EXPECT_THAT(info.hit_section_ids_mask() & 1U << 3, IsTrue());
}
TEST(DocHitInfoTest, MergeSectionsFromDifferentDocumentId) {
// Merging infos with different document_ids works.
DocHitInfo info1(kSomeDocumentId);
DocHitInfo info2(kSomeOtherDocumentId);
info2.UpdateSection(7, 12);
info1.MergeSectionsFrom(info2);
EXPECT_THAT(info1.max_hit_score(7), Eq(12));
EXPECT_THAT(info1.document_id(), Eq(kSomeDocumentId));
}
TEST(DocHitInfoTest, MergeSectionsFromKeepsOldSection) {
// Merging shouldn't override sections that are present info1, but not present
// in info2.
DocHitInfo info1(kSomeDocumentId);
info1.UpdateSection(3, 16);
DocHitInfo info2(kSomeDocumentId);
info1.MergeSectionsFrom(info2);
EXPECT_THAT(info1.max_hit_score(3), Eq(16));
}
TEST(DocHitInfoTest, MergeSectionsFromAddsNewSection) {
// Merging should add sections that were not present in info1, but are present
// in info2.
DocHitInfo info1(kSomeDocumentId);
DocHitInfo info2(kSomeDocumentId);
info2.UpdateSection(7, 12);
info1.MergeSectionsFrom(info2);
EXPECT_THAT(info1.max_hit_score(7), Eq(12));
}
TEST(DocHitInfoTest, MergeSectionsFromSetsHigherHitScore) {
// Merging should override the value of a section in info1 if the same section
// is present in info2 with a higher hit score.
DocHitInfo info1(kSomeDocumentId);
info1.UpdateSection(2, 77);
DocHitInfo info2(kSomeDocumentId);
info2.UpdateSection(2, 89);
info1.MergeSectionsFrom(info2);
EXPECT_THAT(info1.max_hit_score(2), Eq(89));
}
TEST(DocHitInfoTest, MergeSectionsFromDoesNotSetLowerHitScore) {
// Merging should not override the hit score of a section in info1 if the same
// section is present in info2 but with a lower hit score.
DocHitInfo info1(kSomeDocumentId);
info1.UpdateSection(5, 108);
DocHitInfo info2(kSomeDocumentId);
info2.UpdateSection(5, 13);
info1.MergeSectionsFrom(info2);
EXPECT_THAT(info1.max_hit_score(5), Eq(108));
}
TEST(DocHitInfoTest, Comparison) {
constexpr DocumentId kDocumentId = 1;
DocHitInfo info(kDocumentId);
info.UpdateSection(1, 12);
constexpr DocumentId kHighDocumentId = 15;
DocHitInfo high_document_id_info(kHighDocumentId);
high_document_id_info.UpdateSection(1, 12);
DocHitInfo high_section_id_info(kDocumentId);
high_section_id_info.UpdateSection(1, 12);
high_section_id_info.UpdateSection(6, Hit::kDefaultHitScore);
std::vector<DocHitInfo> infos{info, high_document_id_info,
high_section_id_info};
std::sort(infos.begin(), infos.end());
EXPECT_THAT(infos,
ElementsAre(high_document_id_info, info, high_section_id_info));
// There are no requirements for how DocHitInfos with the same DocumentIds and
// hit masks will compare, but they must not be equal.
DocHitInfo different_hit_score_info(kDocumentId);
different_hit_score_info.UpdateSection(1, 76);
EXPECT_THAT(info < different_hit_score_info,
Ne(different_hit_score_info < info));
}
} // namespace lib
} // namespace icing