1*8b6cd535SAndroid Build Coastguard Worker // Copyright (C) 2024 Google LLC
2*8b6cd535SAndroid Build Coastguard Worker //
3*8b6cd535SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*8b6cd535SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*8b6cd535SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*8b6cd535SAndroid Build Coastguard Worker //
7*8b6cd535SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*8b6cd535SAndroid Build Coastguard Worker //
9*8b6cd535SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*8b6cd535SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*8b6cd535SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*8b6cd535SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*8b6cd535SAndroid Build Coastguard Worker // limitations under the License.
14*8b6cd535SAndroid Build Coastguard Worker
15*8b6cd535SAndroid Build Coastguard Worker #include "icing/index/embedding-indexing-handler.h"
16*8b6cd535SAndroid Build Coastguard Worker
17*8b6cd535SAndroid Build Coastguard Worker #include <initializer_list>
18*8b6cd535SAndroid Build Coastguard Worker #include <memory>
19*8b6cd535SAndroid Build Coastguard Worker #include <string>
20*8b6cd535SAndroid Build Coastguard Worker #include <string_view>
21*8b6cd535SAndroid Build Coastguard Worker #include <utility>
22*8b6cd535SAndroid Build Coastguard Worker
23*8b6cd535SAndroid Build Coastguard Worker #include "icing/text_classifier/lib3/utils/base/status.h"
24*8b6cd535SAndroid Build Coastguard Worker #include "gmock/gmock.h"
25*8b6cd535SAndroid Build Coastguard Worker #include "gtest/gtest.h"
26*8b6cd535SAndroid Build Coastguard Worker #include "icing/document-builder.h"
27*8b6cd535SAndroid Build Coastguard Worker #include "icing/feature-flags.h"
28*8b6cd535SAndroid Build Coastguard Worker #include "icing/file/filesystem.h"
29*8b6cd535SAndroid Build Coastguard Worker #include "icing/file/portable-file-backed-proto-log.h"
30*8b6cd535SAndroid Build Coastguard Worker #include "icing/index/embed/embedding-hit.h"
31*8b6cd535SAndroid Build Coastguard Worker #include "icing/index/embed/embedding-index.h"
32*8b6cd535SAndroid Build Coastguard Worker #include "icing/index/embed/quantizer.h"
33*8b6cd535SAndroid Build Coastguard Worker #include "icing/index/hit/hit.h"
34*8b6cd535SAndroid Build Coastguard Worker #include "icing/portable/platform.h"
35*8b6cd535SAndroid Build Coastguard Worker #include "icing/proto/document_wrapper.pb.h"
36*8b6cd535SAndroid Build Coastguard Worker #include "icing/proto/schema.pb.h"
37*8b6cd535SAndroid Build Coastguard Worker #include "icing/schema-builder.h"
38*8b6cd535SAndroid Build Coastguard Worker #include "icing/schema/schema-store.h"
39*8b6cd535SAndroid Build Coastguard Worker #include "icing/schema/section.h"
40*8b6cd535SAndroid Build Coastguard Worker #include "icing/store/document-id.h"
41*8b6cd535SAndroid Build Coastguard Worker #include "icing/store/document-store.h"
42*8b6cd535SAndroid Build Coastguard Worker #include "icing/testing/common-matchers.h"
43*8b6cd535SAndroid Build Coastguard Worker #include "icing/testing/embedding-test-utils.h"
44*8b6cd535SAndroid Build Coastguard Worker #include "icing/testing/fake-clock.h"
45*8b6cd535SAndroid Build Coastguard Worker #include "icing/testing/test-data.h"
46*8b6cd535SAndroid Build Coastguard Worker #include "icing/testing/test-feature-flags.h"
47*8b6cd535SAndroid Build Coastguard Worker #include "icing/testing/tmp-directory.h"
48*8b6cd535SAndroid Build Coastguard Worker #include "icing/tokenization/language-segmenter-factory.h"
49*8b6cd535SAndroid Build Coastguard Worker #include "icing/tokenization/language-segmenter.h"
50*8b6cd535SAndroid Build Coastguard Worker #include "icing/util/icu-data-file-helper.h"
51*8b6cd535SAndroid Build Coastguard Worker #include "icing/util/tokenized-document.h"
52*8b6cd535SAndroid Build Coastguard Worker #include "unicode/uloc.h"
53*8b6cd535SAndroid Build Coastguard Worker
54*8b6cd535SAndroid Build Coastguard Worker namespace icing {
55*8b6cd535SAndroid Build Coastguard Worker namespace lib {
56*8b6cd535SAndroid Build Coastguard Worker
57*8b6cd535SAndroid Build Coastguard Worker namespace {
58*8b6cd535SAndroid Build Coastguard Worker
59*8b6cd535SAndroid Build Coastguard Worker using ::testing::ElementsAre;
60*8b6cd535SAndroid Build Coastguard Worker using ::testing::Eq;
61*8b6cd535SAndroid Build Coastguard Worker using ::testing::FloatNear;
62*8b6cd535SAndroid Build Coastguard Worker using ::testing::IsEmpty;
63*8b6cd535SAndroid Build Coastguard Worker using ::testing::IsTrue;
64*8b6cd535SAndroid Build Coastguard Worker using ::testing::Pointwise;
65*8b6cd535SAndroid Build Coastguard Worker
66*8b6cd535SAndroid Build Coastguard Worker // Indexable properties (section) and section id. Section id is determined by
67*8b6cd535SAndroid Build Coastguard Worker // the lexicographical order of indexable property paths.
68*8b6cd535SAndroid Build Coastguard Worker // Schema type with indexable properties: FakeType
69*8b6cd535SAndroid Build Coastguard Worker // Section id = 0: "body"
70*8b6cd535SAndroid Build Coastguard Worker // Section id = 1: "bodyEmbedding"
71*8b6cd535SAndroid Build Coastguard Worker // Section id = 2: "quantizedEmbedding"
72*8b6cd535SAndroid Build Coastguard Worker // Section id = 3: "title"
73*8b6cd535SAndroid Build Coastguard Worker // Section id = 4: "titleEmbedding"
74*8b6cd535SAndroid Build Coastguard Worker static constexpr std::string_view kFakeType = "FakeType";
75*8b6cd535SAndroid Build Coastguard Worker static constexpr std::string_view kPropertyBody = "body";
76*8b6cd535SAndroid Build Coastguard Worker static constexpr std::string_view kPropertyBodyEmbedding = "bodyEmbedding";
77*8b6cd535SAndroid Build Coastguard Worker static constexpr std::string_view kPropertyQuantizedEmbedding =
78*8b6cd535SAndroid Build Coastguard Worker "quantizedEmbedding";
79*8b6cd535SAndroid Build Coastguard Worker static constexpr std::string_view kPropertyTitle = "title";
80*8b6cd535SAndroid Build Coastguard Worker static constexpr std::string_view kPropertyTitleEmbedding = "titleEmbedding";
81*8b6cd535SAndroid Build Coastguard Worker static constexpr std::string_view kPropertyNonIndexableEmbedding =
82*8b6cd535SAndroid Build Coastguard Worker "nonIndexableEmbedding";
83*8b6cd535SAndroid Build Coastguard Worker
84*8b6cd535SAndroid Build Coastguard Worker static constexpr SectionId kSectionIdBodyEmbedding = 1;
85*8b6cd535SAndroid Build Coastguard Worker static constexpr SectionId kSectionIdQuantizedEmbedding = 2;
86*8b6cd535SAndroid Build Coastguard Worker static constexpr SectionId kSectionIdTitleEmbedding = 4;
87*8b6cd535SAndroid Build Coastguard Worker
88*8b6cd535SAndroid Build Coastguard Worker // Schema type with nested indexable properties: FakeCollectionType
89*8b6cd535SAndroid Build Coastguard Worker // Section id = 0: "collection.body"
90*8b6cd535SAndroid Build Coastguard Worker // Section id = 1: "collection.bodyEmbedding"
91*8b6cd535SAndroid Build Coastguard Worker // Section id = 2: "collection.quantizedEmbedding"
92*8b6cd535SAndroid Build Coastguard Worker // Section id = 3: "collection.title"
93*8b6cd535SAndroid Build Coastguard Worker // Section id = 4: "collection.titleEmbedding"
94*8b6cd535SAndroid Build Coastguard Worker // Section id = 5: "fullDocEmbedding"
95*8b6cd535SAndroid Build Coastguard Worker static constexpr std::string_view kFakeCollectionType = "FakeCollectionType";
96*8b6cd535SAndroid Build Coastguard Worker static constexpr std::string_view kPropertyCollection = "collection";
97*8b6cd535SAndroid Build Coastguard Worker static constexpr std::string_view kPropertyFullDocEmbedding =
98*8b6cd535SAndroid Build Coastguard Worker "fullDocEmbedding";
99*8b6cd535SAndroid Build Coastguard Worker
100*8b6cd535SAndroid Build Coastguard Worker static constexpr SectionId kSectionIdNestedBodyEmbedding = 1;
101*8b6cd535SAndroid Build Coastguard Worker static constexpr SectionId kSectionIdNestedQuantizedEmbedding = 2;
102*8b6cd535SAndroid Build Coastguard Worker static constexpr SectionId kSectionIdNestedTitleEmbedding = 4;
103*8b6cd535SAndroid Build Coastguard Worker static constexpr SectionId kSectionIdFullDocEmbedding = 5;
104*8b6cd535SAndroid Build Coastguard Worker
105*8b6cd535SAndroid Build Coastguard Worker constexpr float kEpsQuantized = 0.01f;
106*8b6cd535SAndroid Build Coastguard Worker
107*8b6cd535SAndroid Build Coastguard Worker class EmbeddingIndexingHandlerTest : public ::testing::Test {
108*8b6cd535SAndroid Build Coastguard Worker protected:
SetUp()109*8b6cd535SAndroid Build Coastguard Worker void SetUp() override {
110*8b6cd535SAndroid Build Coastguard Worker feature_flags_ = std::make_unique<FeatureFlags>(GetTestFeatureFlags());
111*8b6cd535SAndroid Build Coastguard Worker if (!IsCfStringTokenization() && !IsReverseJniTokenization()) {
112*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK(
113*8b6cd535SAndroid Build Coastguard Worker // File generated via icu_data_file rule in //icing/BUILD.
114*8b6cd535SAndroid Build Coastguard Worker icu_data_file_helper::SetUpIcuDataFile(
115*8b6cd535SAndroid Build Coastguard Worker GetTestFilePath("icing/icu.dat")));
116*8b6cd535SAndroid Build Coastguard Worker }
117*8b6cd535SAndroid Build Coastguard Worker
118*8b6cd535SAndroid Build Coastguard Worker base_dir_ = GetTestTempDir() + "/icing_test";
119*8b6cd535SAndroid Build Coastguard Worker ASSERT_THAT(filesystem_.CreateDirectoryRecursively(base_dir_.c_str()),
120*8b6cd535SAndroid Build Coastguard Worker IsTrue());
121*8b6cd535SAndroid Build Coastguard Worker
122*8b6cd535SAndroid Build Coastguard Worker embedding_index_working_path_ = base_dir_ + "/embedding_index";
123*8b6cd535SAndroid Build Coastguard Worker schema_store_dir_ = base_dir_ + "/schema_store";
124*8b6cd535SAndroid Build Coastguard Worker document_store_dir_ = base_dir_ + "/document_store";
125*8b6cd535SAndroid Build Coastguard Worker
126*8b6cd535SAndroid Build Coastguard Worker language_segmenter_factory::SegmenterOptions segmenter_options(ULOC_US);
127*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
128*8b6cd535SAndroid Build Coastguard Worker lang_segmenter_,
129*8b6cd535SAndroid Build Coastguard Worker language_segmenter_factory::Create(std::move(segmenter_options)));
130*8b6cd535SAndroid Build Coastguard Worker
131*8b6cd535SAndroid Build Coastguard Worker ASSERT_THAT(
132*8b6cd535SAndroid Build Coastguard Worker filesystem_.CreateDirectoryRecursively(schema_store_dir_.c_str()),
133*8b6cd535SAndroid Build Coastguard Worker IsTrue());
134*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
135*8b6cd535SAndroid Build Coastguard Worker schema_store_, SchemaStore::Create(&filesystem_, schema_store_dir_,
136*8b6cd535SAndroid Build Coastguard Worker &fake_clock_, feature_flags_.get()));
137*8b6cd535SAndroid Build Coastguard Worker SchemaProto schema =
138*8b6cd535SAndroid Build Coastguard Worker SchemaBuilder()
139*8b6cd535SAndroid Build Coastguard Worker .AddType(
140*8b6cd535SAndroid Build Coastguard Worker SchemaTypeConfigBuilder()
141*8b6cd535SAndroid Build Coastguard Worker .SetType(kFakeType)
142*8b6cd535SAndroid Build Coastguard Worker .AddProperty(PropertyConfigBuilder()
143*8b6cd535SAndroid Build Coastguard Worker .SetName(kPropertyTitle)
144*8b6cd535SAndroid Build Coastguard Worker .SetDataTypeString(TERM_MATCH_EXACT,
145*8b6cd535SAndroid Build Coastguard Worker TOKENIZER_PLAIN)
146*8b6cd535SAndroid Build Coastguard Worker .SetCardinality(CARDINALITY_OPTIONAL))
147*8b6cd535SAndroid Build Coastguard Worker .AddProperty(PropertyConfigBuilder()
148*8b6cd535SAndroid Build Coastguard Worker .SetName(kPropertyBody)
149*8b6cd535SAndroid Build Coastguard Worker .SetDataTypeString(TERM_MATCH_EXACT,
150*8b6cd535SAndroid Build Coastguard Worker TOKENIZER_PLAIN)
151*8b6cd535SAndroid Build Coastguard Worker .SetCardinality(CARDINALITY_REPEATED))
152*8b6cd535SAndroid Build Coastguard Worker .AddProperty(
153*8b6cd535SAndroid Build Coastguard Worker PropertyConfigBuilder()
154*8b6cd535SAndroid Build Coastguard Worker .SetName(kPropertyTitleEmbedding)
155*8b6cd535SAndroid Build Coastguard Worker .SetDataTypeVector(
156*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndexingConfig::EmbeddingIndexingType::
157*8b6cd535SAndroid Build Coastguard Worker LINEAR_SEARCH)
158*8b6cd535SAndroid Build Coastguard Worker .SetCardinality(CARDINALITY_OPTIONAL))
159*8b6cd535SAndroid Build Coastguard Worker .AddProperty(
160*8b6cd535SAndroid Build Coastguard Worker PropertyConfigBuilder()
161*8b6cd535SAndroid Build Coastguard Worker .SetName(kPropertyBodyEmbedding)
162*8b6cd535SAndroid Build Coastguard Worker .SetDataTypeVector(
163*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndexingConfig::EmbeddingIndexingType::
164*8b6cd535SAndroid Build Coastguard Worker LINEAR_SEARCH)
165*8b6cd535SAndroid Build Coastguard Worker .SetCardinality(CARDINALITY_REPEATED))
166*8b6cd535SAndroid Build Coastguard Worker .AddProperty(
167*8b6cd535SAndroid Build Coastguard Worker PropertyConfigBuilder()
168*8b6cd535SAndroid Build Coastguard Worker .SetName(kPropertyQuantizedEmbedding)
169*8b6cd535SAndroid Build Coastguard Worker .SetDataTypeVector(
170*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndexingConfig::EmbeddingIndexingType::
171*8b6cd535SAndroid Build Coastguard Worker LINEAR_SEARCH,
172*8b6cd535SAndroid Build Coastguard Worker QUANTIZATION_TYPE_QUANTIZE_8_BIT)
173*8b6cd535SAndroid Build Coastguard Worker .SetCardinality(CARDINALITY_REPEATED))
174*8b6cd535SAndroid Build Coastguard Worker .AddProperty(PropertyConfigBuilder()
175*8b6cd535SAndroid Build Coastguard Worker .SetName(kPropertyNonIndexableEmbedding)
176*8b6cd535SAndroid Build Coastguard Worker .SetDataType(TYPE_VECTOR)
177*8b6cd535SAndroid Build Coastguard Worker .SetCardinality(CARDINALITY_REPEATED)))
178*8b6cd535SAndroid Build Coastguard Worker .AddType(SchemaTypeConfigBuilder()
179*8b6cd535SAndroid Build Coastguard Worker .SetType(kFakeCollectionType)
180*8b6cd535SAndroid Build Coastguard Worker .AddProperty(PropertyConfigBuilder()
181*8b6cd535SAndroid Build Coastguard Worker .SetName(kPropertyCollection)
182*8b6cd535SAndroid Build Coastguard Worker .SetDataTypeDocument(
183*8b6cd535SAndroid Build Coastguard Worker kFakeType,
184*8b6cd535SAndroid Build Coastguard Worker /*index_nested_properties=*/true)
185*8b6cd535SAndroid Build Coastguard Worker .SetCardinality(CARDINALITY_REPEATED))
186*8b6cd535SAndroid Build Coastguard Worker .AddProperty(
187*8b6cd535SAndroid Build Coastguard Worker PropertyConfigBuilder()
188*8b6cd535SAndroid Build Coastguard Worker .SetName(kPropertyFullDocEmbedding)
189*8b6cd535SAndroid Build Coastguard Worker .SetDataTypeVector(
190*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndexingConfig::
191*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndexingType::LINEAR_SEARCH)
192*8b6cd535SAndroid Build Coastguard Worker .SetCardinality(CARDINALITY_OPTIONAL)))
193*8b6cd535SAndroid Build Coastguard Worker .Build();
194*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK(schema_store_->SetSchema(
195*8b6cd535SAndroid Build Coastguard Worker schema, /*ignore_errors_and_delete_documents=*/false,
196*8b6cd535SAndroid Build Coastguard Worker /*allow_circular_schema_definitions=*/false));
197*8b6cd535SAndroid Build Coastguard Worker
198*8b6cd535SAndroid Build Coastguard Worker ASSERT_TRUE(
199*8b6cd535SAndroid Build Coastguard Worker filesystem_.CreateDirectoryRecursively(document_store_dir_.c_str()));
200*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
201*8b6cd535SAndroid Build Coastguard Worker DocumentStore::CreateResult doc_store_create_result,
202*8b6cd535SAndroid Build Coastguard Worker DocumentStore::Create(&filesystem_, document_store_dir_, &fake_clock_,
203*8b6cd535SAndroid Build Coastguard Worker schema_store_.get(), feature_flags_.get(),
204*8b6cd535SAndroid Build Coastguard Worker /*force_recovery_and_revalidate_documents=*/false,
205*8b6cd535SAndroid Build Coastguard Worker /*pre_mapping_fbv=*/false,
206*8b6cd535SAndroid Build Coastguard Worker /*use_persistent_hash_map=*/true,
207*8b6cd535SAndroid Build Coastguard Worker PortableFileBackedProtoLog<
208*8b6cd535SAndroid Build Coastguard Worker DocumentWrapper>::kDefaultCompressionLevel,
209*8b6cd535SAndroid Build Coastguard Worker /*initialize_stats=*/nullptr));
210*8b6cd535SAndroid Build Coastguard Worker document_store_ = std::move(doc_store_create_result.document_store);
211*8b6cd535SAndroid Build Coastguard Worker
212*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
213*8b6cd535SAndroid Build Coastguard Worker embedding_index_,
214*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndex::Create(&filesystem_, embedding_index_working_path_,
215*8b6cd535SAndroid Build Coastguard Worker &fake_clock_, feature_flags_.get()));
216*8b6cd535SAndroid Build Coastguard Worker }
217*8b6cd535SAndroid Build Coastguard Worker
TearDown()218*8b6cd535SAndroid Build Coastguard Worker void TearDown() override {
219*8b6cd535SAndroid Build Coastguard Worker document_store_.reset();
220*8b6cd535SAndroid Build Coastguard Worker schema_store_.reset();
221*8b6cd535SAndroid Build Coastguard Worker lang_segmenter_.reset();
222*8b6cd535SAndroid Build Coastguard Worker embedding_index_.reset();
223*8b6cd535SAndroid Build Coastguard Worker
224*8b6cd535SAndroid Build Coastguard Worker filesystem_.DeleteDirectoryRecursively(base_dir_.c_str());
225*8b6cd535SAndroid Build Coastguard Worker }
226*8b6cd535SAndroid Build Coastguard Worker
227*8b6cd535SAndroid Build Coastguard Worker std::unique_ptr<FeatureFlags> feature_flags_;
228*8b6cd535SAndroid Build Coastguard Worker Filesystem filesystem_;
229*8b6cd535SAndroid Build Coastguard Worker FakeClock fake_clock_;
230*8b6cd535SAndroid Build Coastguard Worker std::string base_dir_;
231*8b6cd535SAndroid Build Coastguard Worker std::string embedding_index_working_path_;
232*8b6cd535SAndroid Build Coastguard Worker std::string schema_store_dir_;
233*8b6cd535SAndroid Build Coastguard Worker std::string document_store_dir_;
234*8b6cd535SAndroid Build Coastguard Worker
235*8b6cd535SAndroid Build Coastguard Worker std::unique_ptr<EmbeddingIndex> embedding_index_;
236*8b6cd535SAndroid Build Coastguard Worker std::unique_ptr<LanguageSegmenter> lang_segmenter_;
237*8b6cd535SAndroid Build Coastguard Worker std::unique_ptr<SchemaStore> schema_store_;
238*8b6cd535SAndroid Build Coastguard Worker std::unique_ptr<DocumentStore> document_store_;
239*8b6cd535SAndroid Build Coastguard Worker };
240*8b6cd535SAndroid Build Coastguard Worker
241*8b6cd535SAndroid Build Coastguard Worker } // namespace
242*8b6cd535SAndroid Build Coastguard Worker
TEST_F(EmbeddingIndexingHandlerTest,CreationWithNullPointerShouldFail)243*8b6cd535SAndroid Build Coastguard Worker TEST_F(EmbeddingIndexingHandlerTest, CreationWithNullPointerShouldFail) {
244*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(EmbeddingIndexingHandler::Create(/*clock=*/nullptr,
245*8b6cd535SAndroid Build Coastguard Worker embedding_index_.get(),
246*8b6cd535SAndroid Build Coastguard Worker /*enable_embedding_index=*/true),
247*8b6cd535SAndroid Build Coastguard Worker StatusIs(libtextclassifier3::StatusCode::FAILED_PRECONDITION));
248*8b6cd535SAndroid Build Coastguard Worker
249*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(EmbeddingIndexingHandler::Create(&fake_clock_,
250*8b6cd535SAndroid Build Coastguard Worker /*embedding_index=*/nullptr,
251*8b6cd535SAndroid Build Coastguard Worker /*enable_embedding_index=*/true),
252*8b6cd535SAndroid Build Coastguard Worker StatusIs(libtextclassifier3::StatusCode::FAILED_PRECONDITION));
253*8b6cd535SAndroid Build Coastguard Worker }
254*8b6cd535SAndroid Build Coastguard Worker
TEST_F(EmbeddingIndexingHandlerTest,HandleEmbeddingSection)255*8b6cd535SAndroid Build Coastguard Worker TEST_F(EmbeddingIndexingHandlerTest, HandleEmbeddingSection) {
256*8b6cd535SAndroid Build Coastguard Worker DocumentProto document =
257*8b6cd535SAndroid Build Coastguard Worker DocumentBuilder()
258*8b6cd535SAndroid Build Coastguard Worker .SetKey("icing", "fake_type/1")
259*8b6cd535SAndroid Build Coastguard Worker .SetSchema(std::string(kFakeType))
260*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyTitle), "title")
261*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyTitleEmbedding),
262*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.1, 0.2, 0.3}))
263*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyBody), "body")
264*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyBodyEmbedding),
265*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.4, 0.5, 0.6}),
266*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.7, 0.8, 0.9}))
267*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyQuantizedEmbedding),
268*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.1, 0.2, 0.3}),
269*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.4, 0.5, 0.6}))
270*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyNonIndexableEmbedding),
271*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {1.1, 1.2, 1.3}))
272*8b6cd535SAndroid Build Coastguard Worker .Build();
273*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
274*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument tokenized_document,
275*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument::Create(schema_store_.get(), lang_segmenter_.get(),
276*8b6cd535SAndroid Build Coastguard Worker std::move(document)));
277*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
278*8b6cd535SAndroid Build Coastguard Worker DocumentStore::PutResult put_result,
279*8b6cd535SAndroid Build Coastguard Worker document_store_->Put(tokenized_document.document()));
280*8b6cd535SAndroid Build Coastguard Worker DocumentId document_id = put_result.new_document_id;
281*8b6cd535SAndroid Build Coastguard Worker
282*8b6cd535SAndroid Build Coastguard Worker ASSERT_THAT(embedding_index_->last_added_document_id(),
283*8b6cd535SAndroid Build Coastguard Worker Eq(kInvalidDocumentId));
284*8b6cd535SAndroid Build Coastguard Worker // Handle document.
285*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
286*8b6cd535SAndroid Build Coastguard Worker std::unique_ptr<EmbeddingIndexingHandler> handler,
287*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndexingHandler::Create(&fake_clock_, embedding_index_.get(),
288*8b6cd535SAndroid Build Coastguard Worker /*enable_embedding_index=*/true));
289*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(handler->Handle(
290*8b6cd535SAndroid Build Coastguard Worker tokenized_document, document_id, put_result.old_document_id,
291*8b6cd535SAndroid Build Coastguard Worker /*recovery_mode=*/false, /*put_document_stats=*/nullptr),
292*8b6cd535SAndroid Build Coastguard Worker IsOk());
293*8b6cd535SAndroid Build Coastguard Worker
294*8b6cd535SAndroid Build Coastguard Worker // Check index
295*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit hit1(BasicHit(kSectionIdBodyEmbedding, /*document_id=*/0),
296*8b6cd535SAndroid Build Coastguard Worker /*location=*/0);
297*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit hit2(BasicHit(kSectionIdBodyEmbedding, /*document_id=*/0),
298*8b6cd535SAndroid Build Coastguard Worker /*location=*/3);
299*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit hit3(BasicHit(kSectionIdTitleEmbedding, /*document_id=*/0),
300*8b6cd535SAndroid Build Coastguard Worker /*location=*/6);
301*8b6cd535SAndroid Build Coastguard Worker // Quantized embeddings are stored in a different location from unquantized
302*8b6cd535SAndroid Build Coastguard Worker // embeddings, so the location starts from 0 again.
303*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit quantized_hit1(
304*8b6cd535SAndroid Build Coastguard Worker BasicHit(kSectionIdQuantizedEmbedding, /*document_id=*/0),
305*8b6cd535SAndroid Build Coastguard Worker /*location=*/0);
306*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit quantized_hit2(
307*8b6cd535SAndroid Build Coastguard Worker BasicHit(kSectionIdQuantizedEmbedding, /*document_id=*/0),
308*8b6cd535SAndroid Build Coastguard Worker /*location=*/3 + sizeof(Quantizer));
309*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetEmbeddingHitsFromIndex(embedding_index_.get(), /*dimension=*/3,
310*8b6cd535SAndroid Build Coastguard Worker /*model_signature=*/"model"),
311*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(ElementsAre(hit1, hit2, quantized_hit1,
312*8b6cd535SAndroid Build Coastguard Worker quantized_hit2, hit3)));
313*8b6cd535SAndroid Build Coastguard Worker // Check unquantized embedding data
314*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetRawEmbeddingDataFromIndex(embedding_index_.get()),
315*8b6cd535SAndroid Build Coastguard Worker ElementsAre(0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.1, 0.2, 0.3));
316*8b6cd535SAndroid Build Coastguard Worker // Check quantized embedding data
317*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->GetTotalQuantizedVectorSize(),
318*8b6cd535SAndroid Build Coastguard Worker Eq(6 + 2 * sizeof(Quantizer)));
319*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
320*8b6cd535SAndroid Build Coastguard Worker GetAndRestoreQuantizedEmbeddingVectorFromIndex(embedding_index_.get(),
321*8b6cd535SAndroid Build Coastguard Worker quantized_hit1,
322*8b6cd535SAndroid Build Coastguard Worker /*dimension=*/3),
323*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(Pointwise(FloatNear(kEpsQuantized), {0.1, 0.2, 0.3})));
324*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
325*8b6cd535SAndroid Build Coastguard Worker GetAndRestoreQuantizedEmbeddingVectorFromIndex(embedding_index_.get(),
326*8b6cd535SAndroid Build Coastguard Worker quantized_hit2,
327*8b6cd535SAndroid Build Coastguard Worker /*dimension=*/3),
328*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(Pointwise(FloatNear(kEpsQuantized), {0.4, 0.5, 0.6})));
329*8b6cd535SAndroid Build Coastguard Worker
330*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->last_added_document_id(), Eq(document_id));
331*8b6cd535SAndroid Build Coastguard Worker }
332*8b6cd535SAndroid Build Coastguard Worker
TEST_F(EmbeddingIndexingHandlerTest,EmbeddingShouldNotBeIndexedIfDisabled)333*8b6cd535SAndroid Build Coastguard Worker TEST_F(EmbeddingIndexingHandlerTest, EmbeddingShouldNotBeIndexedIfDisabled) {
334*8b6cd535SAndroid Build Coastguard Worker DocumentProto document =
335*8b6cd535SAndroid Build Coastguard Worker DocumentBuilder()
336*8b6cd535SAndroid Build Coastguard Worker .SetKey("icing", "fake_type/1")
337*8b6cd535SAndroid Build Coastguard Worker .SetSchema(std::string(kFakeType))
338*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyTitle), "title")
339*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyTitleEmbedding),
340*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.1, 0.2, 0.3}))
341*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyBody), "body")
342*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyBodyEmbedding),
343*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.4, 0.5, 0.6}),
344*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.7, 0.8, 0.9}))
345*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyNonIndexableEmbedding),
346*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {1.1, 1.2, 1.3}))
347*8b6cd535SAndroid Build Coastguard Worker .Build();
348*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
349*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument tokenized_document,
350*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument::Create(schema_store_.get(), lang_segmenter_.get(),
351*8b6cd535SAndroid Build Coastguard Worker std::move(document)));
352*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
353*8b6cd535SAndroid Build Coastguard Worker DocumentStore::PutResult put_result,
354*8b6cd535SAndroid Build Coastguard Worker document_store_->Put(tokenized_document.document()));
355*8b6cd535SAndroid Build Coastguard Worker DocumentId document_id = put_result.new_document_id;
356*8b6cd535SAndroid Build Coastguard Worker
357*8b6cd535SAndroid Build Coastguard Worker ASSERT_THAT(embedding_index_->last_added_document_id(),
358*8b6cd535SAndroid Build Coastguard Worker Eq(kInvalidDocumentId));
359*8b6cd535SAndroid Build Coastguard Worker // If enable_embedding_index is false, the handler should not index any
360*8b6cd535SAndroid Build Coastguard Worker // embeddings.
361*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
362*8b6cd535SAndroid Build Coastguard Worker std::unique_ptr<EmbeddingIndexingHandler> handler,
363*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndexingHandler::Create(&fake_clock_, embedding_index_.get(),
364*8b6cd535SAndroid Build Coastguard Worker /*enable_embedding_index=*/false));
365*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(handler->Handle(
366*8b6cd535SAndroid Build Coastguard Worker tokenized_document, document_id, put_result.old_document_id,
367*8b6cd535SAndroid Build Coastguard Worker /*recovery_mode=*/false, /*put_document_stats=*/nullptr),
368*8b6cd535SAndroid Build Coastguard Worker IsOk());
369*8b6cd535SAndroid Build Coastguard Worker
370*8b6cd535SAndroid Build Coastguard Worker // Check that the embedding index is empty.
371*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetEmbeddingHitsFromIndex(embedding_index_.get(), /*dimension=*/3,
372*8b6cd535SAndroid Build Coastguard Worker /*model_signature=*/"model"),
373*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(IsEmpty()));
374*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetRawEmbeddingDataFromIndex(embedding_index_.get()), IsEmpty());
375*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->last_added_document_id(), Eq(document_id));
376*8b6cd535SAndroid Build Coastguard Worker }
377*8b6cd535SAndroid Build Coastguard Worker
TEST_F(EmbeddingIndexingHandlerTest,HandleNestedEmbeddingSection)378*8b6cd535SAndroid Build Coastguard Worker TEST_F(EmbeddingIndexingHandlerTest, HandleNestedEmbeddingSection) {
379*8b6cd535SAndroid Build Coastguard Worker DocumentProto document =
380*8b6cd535SAndroid Build Coastguard Worker DocumentBuilder()
381*8b6cd535SAndroid Build Coastguard Worker .SetKey("icing", "fake_collection_type/1")
382*8b6cd535SAndroid Build Coastguard Worker .SetSchema(std::string(kFakeCollectionType))
383*8b6cd535SAndroid Build Coastguard Worker .AddDocumentProperty(
384*8b6cd535SAndroid Build Coastguard Worker std::string(kPropertyCollection),
385*8b6cd535SAndroid Build Coastguard Worker DocumentBuilder()
386*8b6cd535SAndroid Build Coastguard Worker .SetKey("icing", "nested_fake_type/1")
387*8b6cd535SAndroid Build Coastguard Worker .SetSchema(std::string(kFakeType))
388*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyTitle), "title")
389*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyTitleEmbedding),
390*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.1, 0.2, 0.3}))
391*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyBody), "body")
392*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyBodyEmbedding),
393*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.4, 0.5, 0.6}),
394*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.7, 0.8, 0.9}))
395*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyQuantizedEmbedding),
396*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.1, 0.2, 0.3}),
397*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.4, 0.5, 0.6}))
398*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(
399*8b6cd535SAndroid Build Coastguard Worker std::string(kPropertyNonIndexableEmbedding),
400*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {1.1, 1.2, 1.3}))
401*8b6cd535SAndroid Build Coastguard Worker .Build())
402*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyFullDocEmbedding),
403*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {2.1, 2.2, 2.3}))
404*8b6cd535SAndroid Build Coastguard Worker .Build();
405*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
406*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument tokenized_document,
407*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument::Create(schema_store_.get(), lang_segmenter_.get(),
408*8b6cd535SAndroid Build Coastguard Worker std::move(document)));
409*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
410*8b6cd535SAndroid Build Coastguard Worker DocumentStore::PutResult put_result,
411*8b6cd535SAndroid Build Coastguard Worker document_store_->Put(tokenized_document.document()));
412*8b6cd535SAndroid Build Coastguard Worker DocumentId document_id = put_result.new_document_id;
413*8b6cd535SAndroid Build Coastguard Worker
414*8b6cd535SAndroid Build Coastguard Worker ASSERT_THAT(embedding_index_->last_added_document_id(),
415*8b6cd535SAndroid Build Coastguard Worker Eq(kInvalidDocumentId));
416*8b6cd535SAndroid Build Coastguard Worker // Handle document.
417*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
418*8b6cd535SAndroid Build Coastguard Worker std::unique_ptr<EmbeddingIndexingHandler> handler,
419*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndexingHandler::Create(&fake_clock_, embedding_index_.get(),
420*8b6cd535SAndroid Build Coastguard Worker /*enable_embedding_index=*/true));
421*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(handler->Handle(
422*8b6cd535SAndroid Build Coastguard Worker tokenized_document, document_id, put_result.old_document_id,
423*8b6cd535SAndroid Build Coastguard Worker /*recovery_mode=*/false, /*put_document_stats=*/nullptr),
424*8b6cd535SAndroid Build Coastguard Worker IsOk());
425*8b6cd535SAndroid Build Coastguard Worker
426*8b6cd535SAndroid Build Coastguard Worker // Check index
427*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit hit1(BasicHit(kSectionIdNestedBodyEmbedding, /*document_id=*/0),
428*8b6cd535SAndroid Build Coastguard Worker /*location=*/0);
429*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit hit2(BasicHit(kSectionIdNestedBodyEmbedding, /*document_id=*/0),
430*8b6cd535SAndroid Build Coastguard Worker /*location=*/3);
431*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit hit3(BasicHit(kSectionIdNestedTitleEmbedding, /*document_id=*/0),
432*8b6cd535SAndroid Build Coastguard Worker /*location=*/6);
433*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit hit4(BasicHit(kSectionIdFullDocEmbedding, /*document_id=*/0),
434*8b6cd535SAndroid Build Coastguard Worker /*location=*/9);
435*8b6cd535SAndroid Build Coastguard Worker // Quantized embeddings are stored in a different location from unquantized
436*8b6cd535SAndroid Build Coastguard Worker // embeddings, so the location starts from 0 again.
437*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit quantized_hit1(
438*8b6cd535SAndroid Build Coastguard Worker BasicHit(kSectionIdNestedQuantizedEmbedding, /*document_id=*/0),
439*8b6cd535SAndroid Build Coastguard Worker /*location=*/0);
440*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit quantized_hit2(
441*8b6cd535SAndroid Build Coastguard Worker BasicHit(kSectionIdNestedQuantizedEmbedding, /*document_id=*/0),
442*8b6cd535SAndroid Build Coastguard Worker /*location=*/3 + sizeof(Quantizer));
443*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetEmbeddingHitsFromIndex(embedding_index_.get(), /*dimension=*/3,
444*8b6cd535SAndroid Build Coastguard Worker /*model_signature=*/"model"),
445*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(ElementsAre(hit1, hit2, quantized_hit1,
446*8b6cd535SAndroid Build Coastguard Worker quantized_hit2, hit3, hit4)));
447*8b6cd535SAndroid Build Coastguard Worker // Check unquantized embedding data
448*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
449*8b6cd535SAndroid Build Coastguard Worker GetRawEmbeddingDataFromIndex(embedding_index_.get()),
450*8b6cd535SAndroid Build Coastguard Worker ElementsAre(0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.1, 0.2, 0.3, 2.1, 2.2, 2.3));
451*8b6cd535SAndroid Build Coastguard Worker // Check quantized embedding data
452*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->GetTotalQuantizedVectorSize(),
453*8b6cd535SAndroid Build Coastguard Worker Eq(6 + 2 * sizeof(Quantizer)));
454*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
455*8b6cd535SAndroid Build Coastguard Worker GetAndRestoreQuantizedEmbeddingVectorFromIndex(embedding_index_.get(),
456*8b6cd535SAndroid Build Coastguard Worker quantized_hit1,
457*8b6cd535SAndroid Build Coastguard Worker /*dimension=*/3),
458*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(Pointwise(FloatNear(kEpsQuantized), {0.1, 0.2, 0.3})));
459*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
460*8b6cd535SAndroid Build Coastguard Worker GetAndRestoreQuantizedEmbeddingVectorFromIndex(embedding_index_.get(),
461*8b6cd535SAndroid Build Coastguard Worker quantized_hit2,
462*8b6cd535SAndroid Build Coastguard Worker /*dimension=*/3),
463*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(Pointwise(FloatNear(kEpsQuantized), {0.4, 0.5, 0.6})));
464*8b6cd535SAndroid Build Coastguard Worker
465*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->last_added_document_id(), Eq(document_id));
466*8b6cd535SAndroid Build Coastguard Worker }
467*8b6cd535SAndroid Build Coastguard Worker
TEST_F(EmbeddingIndexingHandlerTest,HandleInvalidNewDocumentIdShouldReturnInvalidArgumentError)468*8b6cd535SAndroid Build Coastguard Worker TEST_F(EmbeddingIndexingHandlerTest,
469*8b6cd535SAndroid Build Coastguard Worker HandleInvalidNewDocumentIdShouldReturnInvalidArgumentError) {
470*8b6cd535SAndroid Build Coastguard Worker DocumentProto document =
471*8b6cd535SAndroid Build Coastguard Worker DocumentBuilder()
472*8b6cd535SAndroid Build Coastguard Worker .SetKey("icing", "fake_type/1")
473*8b6cd535SAndroid Build Coastguard Worker .SetSchema(std::string(kFakeType))
474*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyTitle), "title")
475*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyTitleEmbedding),
476*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.1, 0.2, 0.3}))
477*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyBody), "body")
478*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyBodyEmbedding),
479*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.4, 0.5, 0.6}),
480*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.7, 0.8, 0.9}))
481*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyNonIndexableEmbedding),
482*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {1.1, 1.2, 1.3}))
483*8b6cd535SAndroid Build Coastguard Worker .Build();
484*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
485*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument tokenized_document,
486*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument::Create(schema_store_.get(), lang_segmenter_.get(),
487*8b6cd535SAndroid Build Coastguard Worker std::move(document)));
488*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK(document_store_->Put(tokenized_document.document()));
489*8b6cd535SAndroid Build Coastguard Worker
490*8b6cd535SAndroid Build Coastguard Worker static constexpr DocumentId kCurrentDocumentId = 3;
491*8b6cd535SAndroid Build Coastguard Worker embedding_index_->set_last_added_document_id(kCurrentDocumentId);
492*8b6cd535SAndroid Build Coastguard Worker ASSERT_THAT(embedding_index_->last_added_document_id(),
493*8b6cd535SAndroid Build Coastguard Worker Eq(kCurrentDocumentId));
494*8b6cd535SAndroid Build Coastguard Worker
495*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
496*8b6cd535SAndroid Build Coastguard Worker std::unique_ptr<EmbeddingIndexingHandler> handler,
497*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndexingHandler::Create(&fake_clock_, embedding_index_.get(),
498*8b6cd535SAndroid Build Coastguard Worker /*enable_embedding_index=*/true));
499*8b6cd535SAndroid Build Coastguard Worker
500*8b6cd535SAndroid Build Coastguard Worker // Handling document with kInvalidDocumentId should cause a failure, and both
501*8b6cd535SAndroid Build Coastguard Worker // index data and last_added_document_id should remain unchanged.
502*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
503*8b6cd535SAndroid Build Coastguard Worker handler->Handle(tokenized_document, kInvalidDocumentId,
504*8b6cd535SAndroid Build Coastguard Worker /*old_document_id=*/kInvalidDocumentId,
505*8b6cd535SAndroid Build Coastguard Worker /*recovery_mode=*/false, /*put_document_stats=*/nullptr),
506*8b6cd535SAndroid Build Coastguard Worker StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
507*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->last_added_document_id(),
508*8b6cd535SAndroid Build Coastguard Worker Eq(kCurrentDocumentId));
509*8b6cd535SAndroid Build Coastguard Worker // Check that the embedding index should be empty
510*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetEmbeddingHitsFromIndex(embedding_index_.get(), /*dimension=*/3,
511*8b6cd535SAndroid Build Coastguard Worker /*model_signature=*/"model"),
512*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(IsEmpty()));
513*8b6cd535SAndroid Build Coastguard Worker EXPECT_TRUE(embedding_index_->is_empty());
514*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetRawEmbeddingDataFromIndex(embedding_index_.get()), IsEmpty());
515*8b6cd535SAndroid Build Coastguard Worker
516*8b6cd535SAndroid Build Coastguard Worker // Recovery mode should get the same result.
517*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
518*8b6cd535SAndroid Build Coastguard Worker handler->Handle(tokenized_document, kInvalidDocumentId,
519*8b6cd535SAndroid Build Coastguard Worker /*old_document_id=*/kInvalidDocumentId,
520*8b6cd535SAndroid Build Coastguard Worker /*recovery_mode=*/true, /*put_document_stats=*/nullptr),
521*8b6cd535SAndroid Build Coastguard Worker StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
522*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->last_added_document_id(),
523*8b6cd535SAndroid Build Coastguard Worker Eq(kCurrentDocumentId));
524*8b6cd535SAndroid Build Coastguard Worker // Check that the embedding index should be empty
525*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetEmbeddingHitsFromIndex(embedding_index_.get(), /*dimension=*/3,
526*8b6cd535SAndroid Build Coastguard Worker /*model_signature=*/"model"),
527*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(IsEmpty()));
528*8b6cd535SAndroid Build Coastguard Worker EXPECT_TRUE(embedding_index_->is_empty());
529*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetRawEmbeddingDataFromIndex(embedding_index_.get()), IsEmpty());
530*8b6cd535SAndroid Build Coastguard Worker }
531*8b6cd535SAndroid Build Coastguard Worker
TEST_F(EmbeddingIndexingHandlerTest,HandleOutOfOrderDocumentIdShouldReturnInvalidArgumentError)532*8b6cd535SAndroid Build Coastguard Worker TEST_F(EmbeddingIndexingHandlerTest,
533*8b6cd535SAndroid Build Coastguard Worker HandleOutOfOrderDocumentIdShouldReturnInvalidArgumentError) {
534*8b6cd535SAndroid Build Coastguard Worker DocumentProto document =
535*8b6cd535SAndroid Build Coastguard Worker DocumentBuilder()
536*8b6cd535SAndroid Build Coastguard Worker .SetKey("icing", "fake_type/1")
537*8b6cd535SAndroid Build Coastguard Worker .SetSchema(std::string(kFakeType))
538*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyTitle), "title")
539*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyTitleEmbedding),
540*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.1, 0.2, 0.3}))
541*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyBody), "body")
542*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyBodyEmbedding),
543*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.4, 0.5, 0.6}),
544*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.7, 0.8, 0.9}))
545*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyNonIndexableEmbedding),
546*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {1.1, 1.2, 1.3}))
547*8b6cd535SAndroid Build Coastguard Worker .Build();
548*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
549*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument tokenized_document,
550*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument::Create(schema_store_.get(), lang_segmenter_.get(),
551*8b6cd535SAndroid Build Coastguard Worker std::move(document)));
552*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
553*8b6cd535SAndroid Build Coastguard Worker DocumentStore::PutResult put_result,
554*8b6cd535SAndroid Build Coastguard Worker document_store_->Put(tokenized_document.document()));
555*8b6cd535SAndroid Build Coastguard Worker DocumentId document_id = put_result.new_document_id;
556*8b6cd535SAndroid Build Coastguard Worker
557*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
558*8b6cd535SAndroid Build Coastguard Worker std::unique_ptr<EmbeddingIndexingHandler> handler,
559*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndexingHandler::Create(&fake_clock_, embedding_index_.get(),
560*8b6cd535SAndroid Build Coastguard Worker /*enable_embedding_index=*/true));
561*8b6cd535SAndroid Build Coastguard Worker
562*8b6cd535SAndroid Build Coastguard Worker // Handling document with document_id == last_added_document_id should cause a
563*8b6cd535SAndroid Build Coastguard Worker // failure, and both index data and last_added_document_id should remain
564*8b6cd535SAndroid Build Coastguard Worker // unchanged.
565*8b6cd535SAndroid Build Coastguard Worker embedding_index_->set_last_added_document_id(document_id);
566*8b6cd535SAndroid Build Coastguard Worker ASSERT_THAT(embedding_index_->last_added_document_id(), Eq(document_id));
567*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(handler->Handle(
568*8b6cd535SAndroid Build Coastguard Worker tokenized_document, document_id, put_result.old_document_id,
569*8b6cd535SAndroid Build Coastguard Worker /*recovery_mode=*/false, /*put_document_stats=*/nullptr),
570*8b6cd535SAndroid Build Coastguard Worker StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
571*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->last_added_document_id(), Eq(document_id));
572*8b6cd535SAndroid Build Coastguard Worker
573*8b6cd535SAndroid Build Coastguard Worker // Check that the embedding index should be empty
574*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetEmbeddingHitsFromIndex(embedding_index_.get(), /*dimension=*/3,
575*8b6cd535SAndroid Build Coastguard Worker /*model_signature=*/"model"),
576*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(IsEmpty()));
577*8b6cd535SAndroid Build Coastguard Worker EXPECT_TRUE(embedding_index_->is_empty());
578*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetRawEmbeddingDataFromIndex(embedding_index_.get()), IsEmpty());
579*8b6cd535SAndroid Build Coastguard Worker
580*8b6cd535SAndroid Build Coastguard Worker // Handling document with document_id < last_added_document_id should cause a
581*8b6cd535SAndroid Build Coastguard Worker // failure, and both index data and last_added_document_id should remain
582*8b6cd535SAndroid Build Coastguard Worker // unchanged.
583*8b6cd535SAndroid Build Coastguard Worker embedding_index_->set_last_added_document_id(document_id + 1);
584*8b6cd535SAndroid Build Coastguard Worker ASSERT_THAT(embedding_index_->last_added_document_id(), Eq(document_id + 1));
585*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(handler->Handle(
586*8b6cd535SAndroid Build Coastguard Worker tokenized_document, document_id, put_result.old_document_id,
587*8b6cd535SAndroid Build Coastguard Worker /*recovery_mode=*/false, /*put_document_stats=*/nullptr),
588*8b6cd535SAndroid Build Coastguard Worker StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
589*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->last_added_document_id(), Eq(document_id + 1));
590*8b6cd535SAndroid Build Coastguard Worker
591*8b6cd535SAndroid Build Coastguard Worker // Check that the embedding index should be empty
592*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetEmbeddingHitsFromIndex(embedding_index_.get(), /*dimension=*/3,
593*8b6cd535SAndroid Build Coastguard Worker /*model_signature=*/"model"),
594*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(IsEmpty()));
595*8b6cd535SAndroid Build Coastguard Worker EXPECT_TRUE(embedding_index_->is_empty());
596*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetRawEmbeddingDataFromIndex(embedding_index_.get()), IsEmpty());
597*8b6cd535SAndroid Build Coastguard Worker }
598*8b6cd535SAndroid Build Coastguard Worker
TEST_F(EmbeddingIndexingHandlerTest,HandleRecoveryModeShouldIgnoreDocsLELastAddedDocId)599*8b6cd535SAndroid Build Coastguard Worker TEST_F(EmbeddingIndexingHandlerTest,
600*8b6cd535SAndroid Build Coastguard Worker HandleRecoveryModeShouldIgnoreDocsLELastAddedDocId) {
601*8b6cd535SAndroid Build Coastguard Worker DocumentProto document1 =
602*8b6cd535SAndroid Build Coastguard Worker DocumentBuilder()
603*8b6cd535SAndroid Build Coastguard Worker .SetKey("icing", "fake_type/1")
604*8b6cd535SAndroid Build Coastguard Worker .SetSchema(std::string(kFakeType))
605*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyTitle), "title one")
606*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyTitleEmbedding),
607*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.1, 0.2, 0.3}))
608*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyBody), "body one")
609*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyBodyEmbedding),
610*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.4, 0.5, 0.6}),
611*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {0.7, 0.8, 0.9}))
612*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyNonIndexableEmbedding),
613*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {1.1, 1.2, 1.3}))
614*8b6cd535SAndroid Build Coastguard Worker .Build();
615*8b6cd535SAndroid Build Coastguard Worker DocumentProto document2 =
616*8b6cd535SAndroid Build Coastguard Worker DocumentBuilder()
617*8b6cd535SAndroid Build Coastguard Worker .SetKey("icing", "fake_type/2")
618*8b6cd535SAndroid Build Coastguard Worker .SetSchema(std::string(kFakeType))
619*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyTitle), "title two")
620*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyTitleEmbedding),
621*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {10.1, 10.2, 10.3}))
622*8b6cd535SAndroid Build Coastguard Worker .AddStringProperty(std::string(kPropertyBody), "body two")
623*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyBodyEmbedding),
624*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {10.4, 10.5, 10.6}),
625*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {10.7, 10.8, 10.9}))
626*8b6cd535SAndroid Build Coastguard Worker .AddVectorProperty(std::string(kPropertyNonIndexableEmbedding),
627*8b6cd535SAndroid Build Coastguard Worker CreateVector("model", {11.1, 11.2, 11.3}))
628*8b6cd535SAndroid Build Coastguard Worker .Build();
629*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
630*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument tokenized_document1,
631*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument::Create(schema_store_.get(), lang_segmenter_.get(),
632*8b6cd535SAndroid Build Coastguard Worker std::move(document1)));
633*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
634*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument tokenized_document2,
635*8b6cd535SAndroid Build Coastguard Worker TokenizedDocument::Create(schema_store_.get(), lang_segmenter_.get(),
636*8b6cd535SAndroid Build Coastguard Worker std::move(document2)));
637*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
638*8b6cd535SAndroid Build Coastguard Worker DocumentStore::PutResult put_result1,
639*8b6cd535SAndroid Build Coastguard Worker document_store_->Put(tokenized_document1.document()));
640*8b6cd535SAndroid Build Coastguard Worker DocumentId document_id1 = put_result1.new_document_id;
641*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
642*8b6cd535SAndroid Build Coastguard Worker DocumentStore::PutResult put_result2,
643*8b6cd535SAndroid Build Coastguard Worker document_store_->Put(tokenized_document2.document()));
644*8b6cd535SAndroid Build Coastguard Worker DocumentId document_id2 = put_result2.new_document_id;
645*8b6cd535SAndroid Build Coastguard Worker
646*8b6cd535SAndroid Build Coastguard Worker ICING_ASSERT_OK_AND_ASSIGN(
647*8b6cd535SAndroid Build Coastguard Worker std::unique_ptr<EmbeddingIndexingHandler> handler,
648*8b6cd535SAndroid Build Coastguard Worker EmbeddingIndexingHandler::Create(&fake_clock_, embedding_index_.get(),
649*8b6cd535SAndroid Build Coastguard Worker /*enable_embedding_index=*/true));
650*8b6cd535SAndroid Build Coastguard Worker
651*8b6cd535SAndroid Build Coastguard Worker // Handle document with document_id > last_added_document_id in recovery mode.
652*8b6cd535SAndroid Build Coastguard Worker // The handler should index this document and update last_added_document_id.
653*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
654*8b6cd535SAndroid Build Coastguard Worker handler->Handle(tokenized_document1, document_id1,
655*8b6cd535SAndroid Build Coastguard Worker put_result1.old_document_id, /*recovery_mode=*/true,
656*8b6cd535SAndroid Build Coastguard Worker /*put_document_stats=*/nullptr),
657*8b6cd535SAndroid Build Coastguard Worker IsOk());
658*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->last_added_document_id(), Eq(document_id1));
659*8b6cd535SAndroid Build Coastguard Worker
660*8b6cd535SAndroid Build Coastguard Worker // Check index
661*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
662*8b6cd535SAndroid Build Coastguard Worker GetEmbeddingHitsFromIndex(embedding_index_.get(), /*dimension=*/3,
663*8b6cd535SAndroid Build Coastguard Worker /*model_signature=*/"model"),
664*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(ElementsAre(
665*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit(BasicHit(kSectionIdBodyEmbedding, /*document_id=*/0),
666*8b6cd535SAndroid Build Coastguard Worker /*location=*/0),
667*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit(BasicHit(kSectionIdBodyEmbedding, /*document_id=*/0),
668*8b6cd535SAndroid Build Coastguard Worker /*location=*/3),
669*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit(BasicHit(kSectionIdTitleEmbedding, /*document_id=*/0),
670*8b6cd535SAndroid Build Coastguard Worker /*location=*/6))));
671*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetRawEmbeddingDataFromIndex(embedding_index_.get()),
672*8b6cd535SAndroid Build Coastguard Worker ElementsAre(0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.1, 0.2, 0.3));
673*8b6cd535SAndroid Build Coastguard Worker
674*8b6cd535SAndroid Build Coastguard Worker // Handle document with document_id == last_added_document_id in recovery
675*8b6cd535SAndroid Build Coastguard Worker // mode. We should not get any error, but the handler should ignore the
676*8b6cd535SAndroid Build Coastguard Worker // document, so both index data and last_added_document_id should remain
677*8b6cd535SAndroid Build Coastguard Worker // unchanged.
678*8b6cd535SAndroid Build Coastguard Worker embedding_index_->set_last_added_document_id(document_id2);
679*8b6cd535SAndroid Build Coastguard Worker ASSERT_THAT(embedding_index_->last_added_document_id(), Eq(document_id2));
680*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
681*8b6cd535SAndroid Build Coastguard Worker handler->Handle(tokenized_document2, document_id2,
682*8b6cd535SAndroid Build Coastguard Worker put_result2.old_document_id, /*recovery_mode=*/true,
683*8b6cd535SAndroid Build Coastguard Worker /*put_document_stats=*/nullptr),
684*8b6cd535SAndroid Build Coastguard Worker IsOk());
685*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->last_added_document_id(), Eq(document_id2));
686*8b6cd535SAndroid Build Coastguard Worker
687*8b6cd535SAndroid Build Coastguard Worker // Check index
688*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
689*8b6cd535SAndroid Build Coastguard Worker GetEmbeddingHitsFromIndex(embedding_index_.get(), /*dimension=*/3,
690*8b6cd535SAndroid Build Coastguard Worker /*model_signature=*/"model"),
691*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(ElementsAre(
692*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit(BasicHit(kSectionIdBodyEmbedding, /*document_id=*/0),
693*8b6cd535SAndroid Build Coastguard Worker /*location=*/0),
694*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit(BasicHit(kSectionIdBodyEmbedding, /*document_id=*/0),
695*8b6cd535SAndroid Build Coastguard Worker /*location=*/3),
696*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit(BasicHit(kSectionIdTitleEmbedding, /*document_id=*/0),
697*8b6cd535SAndroid Build Coastguard Worker /*location=*/6))));
698*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetRawEmbeddingDataFromIndex(embedding_index_.get()),
699*8b6cd535SAndroid Build Coastguard Worker ElementsAre(0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.1, 0.2, 0.3));
700*8b6cd535SAndroid Build Coastguard Worker
701*8b6cd535SAndroid Build Coastguard Worker // Handle document with document_id < last_added_document_id in recovery mode.
702*8b6cd535SAndroid Build Coastguard Worker // We should not get any error, but the handler should ignore the document, so
703*8b6cd535SAndroid Build Coastguard Worker // both index data and last_added_document_id should remain unchanged.
704*8b6cd535SAndroid Build Coastguard Worker embedding_index_->set_last_added_document_id(document_id2 + 1);
705*8b6cd535SAndroid Build Coastguard Worker ASSERT_THAT(embedding_index_->last_added_document_id(), Eq(document_id2 + 1));
706*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
707*8b6cd535SAndroid Build Coastguard Worker handler->Handle(tokenized_document2, document_id2,
708*8b6cd535SAndroid Build Coastguard Worker put_result2.old_document_id, /*recovery_mode=*/true,
709*8b6cd535SAndroid Build Coastguard Worker /*put_document_stats=*/nullptr),
710*8b6cd535SAndroid Build Coastguard Worker IsOk());
711*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(embedding_index_->last_added_document_id(), Eq(document_id2 + 1));
712*8b6cd535SAndroid Build Coastguard Worker
713*8b6cd535SAndroid Build Coastguard Worker // Check index
714*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(
715*8b6cd535SAndroid Build Coastguard Worker GetEmbeddingHitsFromIndex(embedding_index_.get(), /*dimension=*/3,
716*8b6cd535SAndroid Build Coastguard Worker /*model_signature=*/"model"),
717*8b6cd535SAndroid Build Coastguard Worker IsOkAndHolds(ElementsAre(
718*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit(BasicHit(kSectionIdBodyEmbedding, /*document_id=*/0),
719*8b6cd535SAndroid Build Coastguard Worker /*location=*/0),
720*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit(BasicHit(kSectionIdBodyEmbedding, /*document_id=*/0),
721*8b6cd535SAndroid Build Coastguard Worker /*location=*/3),
722*8b6cd535SAndroid Build Coastguard Worker EmbeddingHit(BasicHit(kSectionIdTitleEmbedding, /*document_id=*/0),
723*8b6cd535SAndroid Build Coastguard Worker /*location=*/6))));
724*8b6cd535SAndroid Build Coastguard Worker EXPECT_THAT(GetRawEmbeddingDataFromIndex(embedding_index_.get()),
725*8b6cd535SAndroid Build Coastguard Worker ElementsAre(0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.1, 0.2, 0.3));
726*8b6cd535SAndroid Build Coastguard Worker }
727*8b6cd535SAndroid Build Coastguard Worker
728*8b6cd535SAndroid Build Coastguard Worker } // namespace lib
729*8b6cd535SAndroid Build Coastguard Worker } // namespace icing
730