Merge remote-tracking branch 'goog/androidx-platform-dev' into sc-dev am: 6bdac48ae6
Original change: https://googleplex-android-review.googlesource.com/c/platform/external/icing/+/14055819
Change-Id: I26e1a2af3686161500bc7e5294ac598e74d266f1
diff --git a/icing/icing-search-engine.cc b/icing/icing-search-engine.cc
index 047fc81..44241bc 100644
--- a/icing/icing-search-engine.cc
+++ b/icing/icing-search-engine.cc
@@ -967,7 +967,7 @@
// Gets unordered results from query processor
auto query_processor_or = QueryProcessor::Create(
index_.get(), language_segmenter_.get(), normalizer_.get(),
- document_store_.get(), schema_store_.get(), clock_.get());
+ document_store_.get(), schema_store_.get());
if (!query_processor_or.ok()) {
TransformStatus(query_processor_or.status(), result_status);
return result_proto;
@@ -985,6 +985,7 @@
ICING_VLOG(2) << "Deleting the docs that matched the query.";
int num_deleted = 0;
+
while (query_results.root_iterator->Advance().ok()) {
ICING_VLOG(3) << "Deleting doc "
<< query_results.root_iterator->doc_hit_info().document_id();
@@ -996,6 +997,7 @@
return result_proto;
}
}
+
if (num_deleted > 0) {
result_proto.mutable_status()->set_code(StatusProto::OK);
} else {
@@ -1346,7 +1348,7 @@
// Gets unordered results from query processor
auto query_processor_or = QueryProcessor::Create(
index_.get(), language_segmenter_.get(), normalizer_.get(),
- document_store_.get(), schema_store_.get(), clock_.get());
+ document_store_.get(), schema_store_.get());
if (!query_processor_or.ok()) {
TransformStatus(query_processor_or.status(), result_status);
return result_proto;
@@ -1449,7 +1451,7 @@
query_stats->set_latency_ms(overall_timer->GetElapsedMilliseconds());
query_stats->set_num_results_returned_current_page(
result_proto.results_size());
- query_stats->set_num_results_snippeted(
+ query_stats->set_num_results_with_snippets(
std::min(result_proto.results_size(),
result_spec.snippet_spec().num_to_snippet()));
return result_proto;
@@ -1533,7 +1535,7 @@
std::max(page_result_state.snippet_context.snippet_spec.num_to_snippet() -
page_result_state.num_previously_returned,
0);
- query_stats->set_num_results_snippeted(
+ query_stats->set_num_results_with_snippets(
std::min(result_proto.results_size(), num_left_to_snippet));
return result_proto;
}
diff --git a/icing/icing-search-engine_benchmark.cc b/icing/icing-search-engine_benchmark.cc
index 9d33a82..af7efa0 100644
--- a/icing/icing-search-engine_benchmark.cc
+++ b/icing/icing-search-engine_benchmark.cc
@@ -39,6 +39,7 @@
#include "icing/proto/search.pb.h"
#include "icing/proto/status.pb.h"
#include "icing/proto/term.pb.h"
+#include "icing/schema-builder.h"
#include "icing/testing/common-matchers.h"
#include "icing/testing/document-generator.h"
#include "icing/testing/random-string.h"
@@ -462,6 +463,70 @@
->ArgPair(10, 32768)
->ArgPair(10, 131072);
+void BM_SearchNoStackOverflow(benchmark::State& state) {
+ // Initialize the filesystem
+ std::string test_dir = GetTestTempDir() + "/icing/benchmark";
+ Filesystem filesystem;
+ DestructibleDirectory ddir(filesystem, test_dir);
+
+ // Create the schema.
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("Message").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("body")
+ .SetDataTypeString(TermMatchType::PREFIX,
+ StringIndexingConfig::TokenizerType::PLAIN)
+ .SetCardinality(PropertyConfigProto::Cardinality::OPTIONAL)))
+ .Build();
+
+ // Create the index.
+ IcingSearchEngineOptions options;
+ options.set_base_dir(test_dir);
+ options.set_index_merge_size(kIcingFullIndexSize);
+ std::unique_ptr<IcingSearchEngine> icing =
+ std::make_unique<IcingSearchEngine>(options);
+
+ ASSERT_THAT(icing->Initialize().status(), ProtoIsOk());
+ ASSERT_THAT(icing->SetSchema(schema).status(), ProtoIsOk());
+
+ // Create a document that has the term "foo"
+ DocumentProto base_document = DocumentBuilder()
+ .SetSchema("Message")
+ .SetNamespace("namespace")
+ .AddStringProperty("body", "foo")
+ .Build();
+
+ // Insert a lot of documents with the term "foo"
+ int64_t num_docs = state.range(0);
+ for (int64_t i = 0; i < num_docs; ++i) {
+ DocumentProto document =
+ DocumentBuilder(base_document).SetUri(std::to_string(i)).Build();
+ ASSERT_THAT(icing->Put(document).status(), ProtoIsOk());
+ }
+
+ // Do a query and exclude documents with the term "foo". The way this is
+ // currently implemented is that we'll iterate over all the documents in the
+ // index, then apply the exclusion check. Since all our documents have "foo",
+ // we'll consider it a "miss". Previously with recursion, we would have
+ // recursed until we got a success, which would never happen causing us to
+ // recurse through all the documents and trigger a stack overflow. With
+ // the iterative implementation, we should avoid this.
+ SearchSpecProto search_spec;
+ search_spec.set_query("-foo");
+ search_spec.set_term_match_type(TermMatchType::PREFIX);
+
+ ResultSpecProto result_spec;
+ ScoringSpecProto scoring_spec;
+ for (auto s : state) {
+ icing->Search(search_spec, scoring_spec, result_spec);
+ }
+}
+// For other reasons, we hit a limit when inserting the ~350,000th document. So
+// cap the limit to 1 << 18.
+BENCHMARK(BM_SearchNoStackOverflow)
+ ->Range(/*start=*/1 << 10, /*limit=*/1 << 18);
+
} // namespace
} // namespace lib
diff --git a/icing/icing-search-engine_test.cc b/icing/icing-search-engine_test.cc
index 471cc7b..ca90b9d 100644
--- a/icing/icing-search-engine_test.cc
+++ b/icing/icing-search-engine_test.cc
@@ -6850,7 +6850,7 @@
exp_stats.set_requested_page_size(2);
exp_stats.set_num_results_returned_current_page(2);
exp_stats.set_num_documents_scored(5);
- exp_stats.set_num_results_snippeted(2);
+ exp_stats.set_num_results_with_snippets(2);
exp_stats.set_latency_ms(5);
exp_stats.set_parse_query_latency_ms(5);
exp_stats.set_scoring_latency_ms(5);
@@ -6868,7 +6868,7 @@
exp_stats.set_is_first_page(false);
exp_stats.set_requested_page_size(2);
exp_stats.set_num_results_returned_current_page(2);
- exp_stats.set_num_results_snippeted(1);
+ exp_stats.set_num_results_with_snippets(1);
exp_stats.set_latency_ms(5);
exp_stats.set_document_retrieval_latency_ms(5);
EXPECT_THAT(search_result.query_stats(), EqualsProto(exp_stats));
@@ -6883,7 +6883,7 @@
exp_stats.set_is_first_page(false);
exp_stats.set_requested_page_size(2);
exp_stats.set_num_results_returned_current_page(1);
- exp_stats.set_num_results_snippeted(0);
+ exp_stats.set_num_results_with_snippets(0);
exp_stats.set_latency_ms(5);
exp_stats.set_document_retrieval_latency_ms(5);
EXPECT_THAT(search_result.query_stats(), EqualsProto(exp_stats));
diff --git a/icing/index/index-processor_test.cc b/icing/index/index-processor_test.cc
index 20e14e9..b7ec09e 100644
--- a/icing/index/index-processor_test.cc
+++ b/icing/index/index-processor_test.cc
@@ -427,9 +427,8 @@
IndexProcessor::Options::TokenLimitBehavior::kReturnError;
ICING_ASSERT_OK_AND_ASSIGN(
- index_processor_,
- IndexProcessor::Create(normalizer_.get(), index_.get(), options,
- &fake_clock_));
+ index_processor_, IndexProcessor::Create(normalizer_.get(), index_.get(),
+ options, &fake_clock_));
DocumentProto document =
DocumentBuilder()
@@ -470,9 +469,8 @@
IndexProcessor::Options::TokenLimitBehavior::kSuppressError;
ICING_ASSERT_OK_AND_ASSIGN(
- index_processor_,
- IndexProcessor::Create(normalizer_.get(), index_.get(), options,
- &fake_clock_));
+ index_processor_, IndexProcessor::Create(normalizer_.get(), index_.get(),
+ options, &fake_clock_));
DocumentProto document =
DocumentBuilder()
@@ -515,9 +513,8 @@
/*max_term_byte_size=*/4));
ICING_ASSERT_OK_AND_ASSIGN(
- index_processor_,
- IndexProcessor::Create(normalizer.get(), index_.get(), options,
- &fake_clock_));
+ index_processor_, IndexProcessor::Create(normalizer.get(), index_.get(),
+ options, &fake_clock_));
DocumentProto document =
DocumentBuilder()
@@ -686,8 +683,8 @@
ICING_ASSERT_OK_AND_ASSIGN(
index_processor_,
- IndexProcessor::Create(normalizer_.get(), index_.get(),
- processor_options, &fake_clock_));
+ IndexProcessor::Create(normalizer_.get(), index_.get(), processor_options,
+ &fake_clock_));
DocumentProto document =
DocumentBuilder()
diff --git a/icing/index/iterator/doc-hit-info-iterator-filter.cc b/icing/index/iterator/doc-hit-info-iterator-filter.cc
index c6cb86d..933f9b5 100644
--- a/icing/index/iterator/doc-hit-info-iterator-filter.cc
+++ b/icing/index/iterator/doc-hit-info-iterator-filter.cc
@@ -31,7 +31,6 @@
#include "icing/store/document-filter-data.h"
#include "icing/store/document-id.h"
#include "icing/store/document-store.h"
-#include "icing/util/clock.h"
namespace icing {
namespace lib {
@@ -39,12 +38,11 @@
DocHitInfoIteratorFilter::DocHitInfoIteratorFilter(
std::unique_ptr<DocHitInfoIterator> delegate,
const DocumentStore* document_store, const SchemaStore* schema_store,
- const Clock* clock, const Options& options)
+ const Options& options)
: delegate_(std::move(delegate)),
document_store_(*document_store),
schema_store_(*schema_store),
- options_(options),
- current_time_milliseconds_(clock->GetSystemTimeMilliseconds()) {
+ options_(options) {
// Precompute all the NamespaceIds
for (std::string_view name_space : options_.namespaces) {
auto namespace_id_or = document_store_.GetNamespaceId(name_space);
@@ -67,61 +65,50 @@
}
libtextclassifier3::Status DocHitInfoIteratorFilter::Advance() {
- if (!delegate_->Advance().ok()) {
- // Didn't find anything on the delegate iterator.
- doc_hit_info_ = DocHitInfo(kInvalidDocumentId);
- hit_intersect_section_ids_mask_ = kSectionIdMaskNone;
- return absl_ports::ResourceExhaustedError(
- "No more DocHitInfos in iterator");
+ while (delegate_->Advance().ok()) {
+ if (!document_store_.DoesDocumentExist(
+ delegate_->doc_hit_info().document_id())) {
+ // Document doesn't exist, keep searching. This handles deletions and
+ // expired documents.
+ continue;
+ }
+
+ // Try to get the DocumentFilterData
+ auto document_filter_data_or = document_store_.GetDocumentFilterData(
+ delegate_->doc_hit_info().document_id());
+ if (!document_filter_data_or.ok()) {
+ // Didn't find the DocumentFilterData in the filter cache. This could be
+ // because the DocumentId isn't valid or the filter cache is in some
+ // invalid state. This is bad, but not the query's responsibility to fix,
+ // so just skip this result for now.
+ continue;
+ }
+ // We should be guaranteed that this exists now.
+ DocumentFilterData data = std::move(document_filter_data_or).ValueOrDie();
+
+ if (!options_.namespaces.empty() &&
+ target_namespace_ids_.count(data.namespace_id()) == 0) {
+ // Doesn't match one of the specified namespaces. Keep searching
+ continue;
+ }
+
+ if (!options_.schema_types.empty() &&
+ target_schema_type_ids_.count(data.schema_type_id()) == 0) {
+ // Doesn't match one of the specified schema types. Keep searching
+ continue;
+ }
+
+ // Satisfied all our specified filters
+ doc_hit_info_ = delegate_->doc_hit_info();
+ hit_intersect_section_ids_mask_ =
+ delegate_->hit_intersect_section_ids_mask();
+ return libtextclassifier3::Status::OK;
}
- if (current_time_milliseconds_ < 0) {
- // This shouldn't happen, but we add a sanity check here for any unknown
- // errors.
- return absl_ports::InternalError(
- "Couldn't get current time. Try again in a bit");
- }
-
- if (!document_store_.DoesDocumentExist(
- delegate_->doc_hit_info().document_id())) {
- // Document doesn't exist, keep searching
- return Advance();
- }
-
- // Try to get the DocumentFilterData
- auto document_filter_data_or = document_store_.GetDocumentFilterData(
- delegate_->doc_hit_info().document_id());
- if (!document_filter_data_or.ok()) {
- // Didn't find the DocumentFilterData in the filter cache. This could be
- // because the DocumentId isn't valid or the filter cache is in some invalid
- // state. This is bad, but not the query's responsibility to fix, so just
- // skip this result for now.
- return Advance();
- }
- // We should be guaranteed that this exists now.
- DocumentFilterData data = std::move(document_filter_data_or).ValueOrDie();
-
- if (!options_.namespaces.empty() &&
- target_namespace_ids_.count(data.namespace_id()) == 0) {
- // Doesn't match one of the specified namespaces. Keep searching
- return Advance();
- }
-
- if (!options_.schema_types.empty() &&
- target_schema_type_ids_.count(data.schema_type_id()) == 0) {
- // Doesn't match one of the specified schema types. Keep searching
- return Advance();
- }
-
- if (current_time_milliseconds_ >= data.expiration_timestamp_ms()) {
- // Current time has exceeded the document's expiration time
- return Advance();
- }
-
- // Satisfied all our specified filters
- doc_hit_info_ = delegate_->doc_hit_info();
- hit_intersect_section_ids_mask_ = delegate_->hit_intersect_section_ids_mask();
- return libtextclassifier3::Status::OK;
+ // Didn't find anything on the delegate iterator.
+ doc_hit_info_ = DocHitInfo(kInvalidDocumentId);
+ hit_intersect_section_ids_mask_ = kSectionIdMaskNone;
+ return absl_ports::ResourceExhaustedError("No more DocHitInfos in iterator");
}
int32_t DocHitInfoIteratorFilter::GetNumBlocksInspected() const {
diff --git a/icing/index/iterator/doc-hit-info-iterator-filter.h b/icing/index/iterator/doc-hit-info-iterator-filter.h
index 9cee74c..5051607 100644
--- a/icing/index/iterator/doc-hit-info-iterator-filter.h
+++ b/icing/index/iterator/doc-hit-info-iterator-filter.h
@@ -27,7 +27,6 @@
#include "icing/schema/schema-store.h"
#include "icing/store/document-store.h"
#include "icing/store/namespace-id.h"
-#include "icing/util/clock.h"
namespace icing {
namespace lib {
@@ -57,7 +56,7 @@
explicit DocHitInfoIteratorFilter(
std::unique_ptr<DocHitInfoIterator> delegate,
const DocumentStore* document_store, const SchemaStore* schema_store,
- const Clock* clock, const Options& options);
+ const Options& options);
libtextclassifier3::Status Advance() override;
@@ -81,7 +80,6 @@
const Options options_;
std::unordered_set<NamespaceId> target_namespace_ids_;
std::unordered_set<SchemaTypeId> target_schema_type_ids_;
- const int64_t current_time_milliseconds_;
};
} // namespace lib
diff --git a/icing/index/iterator/doc-hit-info-iterator-filter_test.cc b/icing/index/iterator/doc-hit-info-iterator-filter_test.cc
index 8e48123..f80d1ea 100644
--- a/icing/index/iterator/doc-hit-info-iterator-filter_test.cc
+++ b/icing/index/iterator/doc-hit-info-iterator-filter_test.cc
@@ -101,9 +101,9 @@
std::unique_ptr<DocHitInfoIterator> original_iterator_empty =
std::make_unique<DocHitInfoIteratorDummy>();
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator_empty), document_store_.get(),
- schema_store_.get(), &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator_empty),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), IsEmpty());
}
@@ -125,9 +125,9 @@
std::unique_ptr<DocHitInfoIterator> original_iterator =
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator),
ElementsAre(document_id1, document_id3));
@@ -151,9 +151,9 @@
std::unique_ptr<DocHitInfoIterator> original_iterator =
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator),
ElementsAre(document_id1, document_id2, document_id3));
@@ -164,9 +164,9 @@
std::unique_ptr<DocHitInfoIterator> original_iterator =
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(filtered_iterator.Advance(),
StatusIs(libtextclassifier3::StatusCode::RESOURCE_EXHAUSTED));
@@ -178,9 +178,9 @@
std::unique_ptr<DocHitInfoIterator> original_iterator =
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(filtered_iterator.Advance(),
StatusIs(libtextclassifier3::StatusCode::RESOURCE_EXHAUSTED));
@@ -195,9 +195,9 @@
std::unique_ptr<DocHitInfoIterator> original_iterator =
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(filtered_iterator.Advance(),
StatusIs(libtextclassifier3::StatusCode::RESOURCE_EXHAUSTED));
@@ -271,9 +271,9 @@
std::make_unique<DocHitInfoIteratorDummy>();
options_.namespaces = std::vector<std::string_view>{};
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator_empty), document_store_.get(),
- schema_store_.get(), &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator_empty),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), IsEmpty());
}
@@ -289,9 +289,9 @@
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
options_.namespaces = std::vector<std::string_view>{"nonexistent_namespace"};
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), IsEmpty());
}
@@ -306,9 +306,9 @@
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
options_.namespaces = std::vector<std::string_view>{};
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), ElementsAre(document_id1));
}
@@ -330,9 +330,9 @@
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
options_.namespaces = std::vector<std::string_view>{namespace1_};
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator),
ElementsAre(document_id1, document_id2));
@@ -356,9 +356,9 @@
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
options_.namespaces = std::vector<std::string_view>{namespace1_, namespace3_};
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator),
ElementsAre(document_id1, document_id2, document_id4));
@@ -426,9 +426,9 @@
std::make_unique<DocHitInfoIteratorDummy>();
options_.schema_types = std::vector<std::string_view>{};
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator_empty), document_store_.get(),
- schema_store_.get(), &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator_empty),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), IsEmpty());
}
@@ -445,9 +445,9 @@
options_.schema_types =
std::vector<std::string_view>{"nonexistent_schema_type"};
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), IsEmpty());
}
@@ -462,9 +462,9 @@
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
options_.schema_types = std::vector<std::string_view>{};
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), ElementsAre(document_id1));
}
@@ -483,9 +483,9 @@
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
options_.schema_types = std::vector<std::string_view>{schema1_};
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), ElementsAre(document_id1));
}
@@ -506,9 +506,9 @@
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
options_.schema_types = std::vector<std::string_view>{schema2_, schema3_};
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator),
ElementsAre(document_id2, document_id3));
@@ -556,6 +556,16 @@
};
TEST_F(DocHitInfoIteratorExpirationFilterTest, TtlZeroIsntFilteredOut) {
+ // Arbitrary value
+ fake_clock_.SetSystemTimeMilliseconds(100);
+
+ ICING_ASSERT_OK_AND_ASSIGN(
+ DocumentStore::CreateResult create_result,
+ DocumentStore::Create(&filesystem_, test_dir_, &fake_clock_,
+ schema_store_.get()));
+ std::unique_ptr<DocumentStore> document_store =
+ std::move(create_result.document_store);
+
// Insert a document
DocumentProto document = DocumentBuilder()
.SetKey("namespace", "1")
@@ -564,23 +574,30 @@
.SetTtlMs(0)
.Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id1,
- document_store_->Put(document));
+ document_store->Put(document));
std::vector<DocHitInfo> doc_hit_infos = {DocHitInfo(document_id1)};
std::unique_ptr<DocHitInfoIterator> original_iterator =
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
- // Arbitrary value
- fake_clock_.SetSystemTimeMilliseconds(100);
-
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), ElementsAre(document_id1));
}
TEST_F(DocHitInfoIteratorExpirationFilterTest, BeforeTtlNotFilteredOut) {
+ // Arbitrary value, but must be less than document's creation_timestamp + ttl
+ fake_clock_.SetSystemTimeMilliseconds(50);
+
+ ICING_ASSERT_OK_AND_ASSIGN(
+ DocumentStore::CreateResult create_result,
+ DocumentStore::Create(&filesystem_, test_dir_, &fake_clock_,
+ schema_store_.get()));
+ std::unique_ptr<DocumentStore> document_store =
+ std::move(create_result.document_store);
+
// Insert a document
DocumentProto document = DocumentBuilder()
.SetKey("namespace", "1")
@@ -589,92 +606,84 @@
.SetTtlMs(100)
.Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id1,
- document_store_->Put(document));
+ document_store->Put(document));
std::vector<DocHitInfo> doc_hit_infos = {DocHitInfo(document_id1)};
std::unique_ptr<DocHitInfoIterator> original_iterator =
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
- // Arbitrary value, but must be less than document's creation_timestamp + ttl
- fake_clock_.SetSystemTimeMilliseconds(50);
-
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), ElementsAre(document_id1));
}
TEST_F(DocHitInfoIteratorExpirationFilterTest, EqualTtlFilteredOut) {
+ // Current time is exactly the document's creation_timestamp + ttl
+ fake_clock_.SetSystemTimeMilliseconds(150);
+
+ ICING_ASSERT_OK_AND_ASSIGN(
+ DocumentStore::CreateResult create_result,
+ DocumentStore::Create(&filesystem_, test_dir_, &fake_clock_,
+ schema_store_.get()));
+ std::unique_ptr<DocumentStore> document_store =
+ std::move(create_result.document_store);
+
// Insert a document
DocumentProto document = DocumentBuilder()
.SetKey("namespace", "1")
.SetSchema(email_schema_)
- .SetCreationTimestampMs(0)
+ .SetCreationTimestampMs(50)
.SetTtlMs(100)
.Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id1,
- document_store_->Put(document));
+ document_store->Put(document));
std::vector<DocHitInfo> doc_hit_infos = {DocHitInfo(document_id1)};
std::unique_ptr<DocHitInfoIterator> original_iterator =
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
- // Current time is exactly the document's creation_timestamp + ttl
- fake_clock_.SetSystemTimeMilliseconds(100);
-
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), IsEmpty());
}
TEST_F(DocHitInfoIteratorExpirationFilterTest, PastTtlFilteredOut) {
+ // Arbitrary value, but must be greater than the document's
+ // creation_timestamp + ttl
+ fake_clock_.SetSystemTimeMilliseconds(151);
+
+ ICING_ASSERT_OK_AND_ASSIGN(
+ DocumentStore::CreateResult create_result,
+ DocumentStore::Create(&filesystem_, test_dir_, &fake_clock_,
+ schema_store_.get()));
+ std::unique_ptr<DocumentStore> document_store =
+ std::move(create_result.document_store);
+
// Insert a document
DocumentProto document = DocumentBuilder()
.SetKey("namespace", "1")
.SetSchema(email_schema_)
- .SetCreationTimestampMs(0)
+ .SetCreationTimestampMs(50)
.SetTtlMs(100)
.Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id1,
- document_store_->Put(document));
+ document_store->Put(document));
std::vector<DocHitInfo> doc_hit_infos = {DocHitInfo(document_id1)};
std::unique_ptr<DocHitInfoIterator> original_iterator =
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
- // Arbitrary value, but must be greater than the document's
- // creation_timestamp + ttl
- fake_clock_.SetSystemTimeMilliseconds(101);
-
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store.get(),
+ schema_store_.get(), options_);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), IsEmpty());
}
-TEST_F(DocHitInfoIteratorExpirationFilterTest,
- InvalidTimeFiltersReturnsInternalError) {
- // Put something in the original iterator so we don't get a ResourceExhausted
- // error
- std::vector<DocHitInfo> doc_hit_infos = {DocHitInfo(/*document_id_in=*/0)};
- std::unique_ptr<DocHitInfoIterator> original_iterator =
- std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
-
- // -1 is an invalid timestamp
- fake_clock_.SetSystemTimeMilliseconds(-1);
-
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options_);
-
- EXPECT_THAT(filtered_iterator.Advance(),
- StatusIs(libtextclassifier3::StatusCode::INTERNAL));
-}
-
class DocHitInfoIteratorFilterTest : public ::testing::Test {
protected:
DocHitInfoIteratorFilterTest() : test_dir_(GetTestTempDir() + "/icing") {}
@@ -708,7 +717,7 @@
document5_namespace1_schema1_ = DocumentBuilder()
.SetKey(namespace1_, "5")
.SetSchema(schema1_)
- .SetCreationTimestampMs(0)
+ .SetCreationTimestampMs(1)
.SetTtlMs(100)
.Build();
@@ -754,26 +763,36 @@
};
TEST_F(DocHitInfoIteratorFilterTest, CombineAllFiltersOk) {
+ // Filters out document5 since it's expired
+ fake_clock_.SetSystemTimeMilliseconds(199);
+
+ ICING_ASSERT_OK_AND_ASSIGN(
+ DocumentStore::CreateResult create_result,
+ DocumentStore::Create(&filesystem_, test_dir_, &fake_clock_,
+ schema_store_.get()));
+ std::unique_ptr<DocumentStore> document_store =
+ std::move(create_result.document_store);
+
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId document_id1,
- document_store_->Put(document1_namespace1_schema1_));
+ document_store->Put(document1_namespace1_schema1_));
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId document_id2,
- document_store_->Put(document2_namespace1_schema1_));
+ document_store->Put(document2_namespace1_schema1_));
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId document_id3,
- document_store_->Put(document3_namespace2_schema1_));
+ document_store->Put(document3_namespace2_schema1_));
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId document_id4,
- document_store_->Put(document4_namespace1_schema2_));
+ document_store->Put(document4_namespace1_schema2_));
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId document_id5,
- document_store_->Put(document5_namespace1_schema1_));
+ document_store->Put(document5_namespace1_schema1_));
// Deletes document2, causing it to be filtered out
ICING_ASSERT_OK(
- document_store_->Delete(document2_namespace1_schema1_.namespace_(),
- document2_namespace1_schema1_.uri()));
+ document_store->Delete(document2_namespace1_schema1_.namespace_(),
+ document2_namespace1_schema1_.uri()));
std::vector<DocHitInfo> doc_hit_infos = {
DocHitInfo(document_id1), DocHitInfo(document_id2),
@@ -791,13 +810,9 @@
// Filters out document4 by schema type
options.schema_types = std::vector<std::string_view>{schema1_};
- // Filters out document5 since it's expired
- FakeClock fake_clock;
- fake_clock.SetSystemTimeMilliseconds(199);
-
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock, options);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store.get(),
+ schema_store_.get(), options);
EXPECT_THAT(GetDocumentIds(&filtered_iterator), ElementsAre(document_id1));
}
@@ -828,9 +843,9 @@
std::make_unique<DocHitInfoIteratorDummy>(doc_hit_infos);
DocHitInfoIteratorFilter::Options options;
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options);
EXPECT_THAT(GetDocHitInfos(&filtered_iterator),
ElementsAre(EqualsDocHitInfo(document_id1, section_ids1),
@@ -843,9 +858,9 @@
original_iterator->SetNumBlocksInspected(5);
DocHitInfoIteratorFilter::Options options;
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options);
EXPECT_THAT(filtered_iterator.GetNumBlocksInspected(), Eq(5));
}
@@ -855,9 +870,9 @@
original_iterator->SetNumLeafAdvanceCalls(6);
DocHitInfoIteratorFilter::Options options;
- DocHitInfoIteratorFilter filtered_iterator(
- std::move(original_iterator), document_store_.get(), schema_store_.get(),
- &fake_clock_, options);
+ DocHitInfoIteratorFilter filtered_iterator(std::move(original_iterator),
+ document_store_.get(),
+ schema_store_.get(), options);
EXPECT_THAT(filtered_iterator.GetNumLeafAdvanceCalls(), Eq(6));
}
diff --git a/icing/index/iterator/doc-hit-info-iterator-not.cc b/icing/index/iterator/doc-hit-info-iterator-not.cc
index e1ece5c..8fb3659 100644
--- a/icing/index/iterator/doc-hit-info-iterator-not.cc
+++ b/icing/index/iterator/doc-hit-info-iterator-not.cc
@@ -35,30 +35,29 @@
DocHitInfoIteratorAllDocumentId(document_id_limit)) {}
libtextclassifier3::Status DocHitInfoIteratorNot::Advance() {
- if (!all_document_id_iterator_.Advance().ok()) {
- doc_hit_info_ = DocHitInfo(kInvalidDocumentId);
- return absl_ports::ResourceExhaustedError(
- "No more DocHitInfos in iterator");
+ while (all_document_id_iterator_.Advance().ok()) {
+ if (all_document_id_iterator_.doc_hit_info().document_id() <
+ to_be_excluded_->doc_hit_info().document_id()) {
+ // Since DocumentIds are returned from DocHitInfoIterators in decreasing
+ // order, we have passed the last NOT result if we're smaller than its
+ // DocumentId. Advance the NOT result if so.
+ to_be_excluded_->Advance().IgnoreError();
+ }
+
+ if (all_document_id_iterator_.doc_hit_info().document_id() ==
+ to_be_excluded_->doc_hit_info().document_id()) {
+ // This is a NOT result, skip and Advance to the next result.
+ continue;
+ }
+
+ // No errors, we've found a valid result
+ doc_hit_info_ = all_document_id_iterator_.doc_hit_info();
+ return libtextclassifier3::Status::OK;
}
- if (all_document_id_iterator_.doc_hit_info().document_id() <
- to_be_excluded_->doc_hit_info().document_id()) {
- // Since DocumentIds are returned from DocHitInfoIterators in decreasing
- // order, we have passed the last NOT result if we're smaller than its
- // DocumentId. Advance the NOT result if so.
- to_be_excluded_->Advance().IgnoreError();
- }
-
- if (all_document_id_iterator_.doc_hit_info().document_id() ==
- to_be_excluded_->doc_hit_info().document_id()) {
- // This is a NOT result, skip and Advance to the next result.
- return Advance();
- }
-
- // No errors, we've found a valid result
- doc_hit_info_ = all_document_id_iterator_.doc_hit_info();
-
- return libtextclassifier3::Status::OK;
+ // Didn't find a hit, return with error
+ doc_hit_info_ = DocHitInfo(kInvalidDocumentId);
+ return absl_ports::ResourceExhaustedError("No more DocHitInfos in iterator");
}
int32_t DocHitInfoIteratorNot::GetNumBlocksInspected() const {
diff --git a/icing/index/iterator/doc-hit-info-iterator-section-restrict.cc b/icing/index/iterator/doc-hit-info-iterator-section-restrict.cc
index e6ee8e3..034c8cb 100644
--- a/icing/index/iterator/doc-hit-info-iterator-section-restrict.cc
+++ b/icing/index/iterator/doc-hit-info-iterator-section-restrict.cc
@@ -45,56 +45,54 @@
target_section_(target_section) {}
libtextclassifier3::Status DocHitInfoIteratorSectionRestrict::Advance() {
- if (!delegate_->Advance().ok()) {
- // Didn't find anything on the delegate iterator.
- doc_hit_info_ = DocHitInfo(kInvalidDocumentId);
- hit_intersect_section_ids_mask_ = kSectionIdMaskNone;
- return absl_ports::ResourceExhaustedError(
- "No more DocHitInfos in iterator");
- }
+ while (delegate_->Advance().ok()) {
+ DocumentId document_id = delegate_->doc_hit_info().document_id();
- DocumentId document_id = delegate_->doc_hit_info().document_id();
+ SectionIdMask section_id_mask =
+ delegate_->doc_hit_info().hit_section_ids_mask();
- SectionIdMask section_id_mask =
- delegate_->doc_hit_info().hit_section_ids_mask();
-
- auto data_or = document_store_.GetDocumentFilterData(document_id);
- if (!data_or.ok()) {
- // Ran into some error retrieving information on this hit, skip
- return Advance();
- }
-
- // Guaranteed that the DocumentFilterData exists at this point
- DocumentFilterData data = std::move(data_or).ValueOrDie();
- SchemaTypeId schema_type_id = data.schema_type_id();
-
- // A hit can be in multiple sections at once, need to check that at least one
- // of the confirmed section ids match the name of the target section
- while (section_id_mask != 0) {
- // There was a hit in this section id
- SectionId section_id = __builtin_ctz(section_id_mask);
-
- auto section_metadata_or =
- schema_store_.GetSectionMetadata(schema_type_id, section_id);
-
- if (section_metadata_or.ok()) {
- const SectionMetadata* section_metadata =
- section_metadata_or.ValueOrDie();
-
- if (section_metadata->path == target_section_) {
- // The hit was in the target section name, return OK/found
- doc_hit_info_ = delegate_->doc_hit_info();
- hit_intersect_section_ids_mask_ = 1u << section_id;
- return libtextclassifier3::Status::OK;
- }
+ auto data_or = document_store_.GetDocumentFilterData(document_id);
+ if (!data_or.ok()) {
+ // Ran into some error retrieving information on this hit, skip
+ continue;
}
- // Mark this section as checked
- section_id_mask &= ~(1U << section_id);
+ // Guaranteed that the DocumentFilterData exists at this point
+ DocumentFilterData data = std::move(data_or).ValueOrDie();
+ SchemaTypeId schema_type_id = data.schema_type_id();
+
+ // A hit can be in multiple sections at once, need to check that at least
+ // one of the confirmed section ids match the name of the target section
+ while (section_id_mask != 0) {
+ // There was a hit in this section id
+ SectionId section_id = __builtin_ctz(section_id_mask);
+
+ auto section_metadata_or =
+ schema_store_.GetSectionMetadata(schema_type_id, section_id);
+
+ if (section_metadata_or.ok()) {
+ const SectionMetadata* section_metadata =
+ section_metadata_or.ValueOrDie();
+
+ if (section_metadata->path == target_section_) {
+ // The hit was in the target section name, return OK/found
+ doc_hit_info_ = delegate_->doc_hit_info();
+ hit_intersect_section_ids_mask_ = 1u << section_id;
+ return libtextclassifier3::Status::OK;
+ }
+ }
+
+ // Mark this section as checked
+ section_id_mask &= ~(1U << section_id);
+ }
+
+ // Didn't find a matching section name for this hit. Continue.
}
- // Didn't find a matching section name for this hit, go to the next hit
- return Advance();
+ // Didn't find anything on the delegate iterator.
+ doc_hit_info_ = DocHitInfo(kInvalidDocumentId);
+ hit_intersect_section_ids_mask_ = kSectionIdMaskNone;
+ return absl_ports::ResourceExhaustedError("No more DocHitInfos in iterator");
}
int32_t DocHitInfoIteratorSectionRestrict::GetNumBlocksInspected() const {
diff --git a/icing/index/iterator/doc-hit-info-iterator.h b/icing/index/iterator/doc-hit-info-iterator.h
index afb298b..bf90202 100644
--- a/icing/index/iterator/doc-hit-info-iterator.h
+++ b/icing/index/iterator/doc-hit-info-iterator.h
@@ -66,6 +66,8 @@
// Returns:
// OK if was able to advance to a new document_id.
+ // INVALID_ARGUMENT if there are less than 2 iterators for an AND/OR
+ // iterator
// RESOUCE_EXHAUSTED if we've run out of document_ids to iterate over
virtual libtextclassifier3::Status Advance() = 0;
diff --git a/icing/index/iterator/doc-hit-info-iterator_benchmark.cc b/icing/index/iterator/doc-hit-info-iterator_benchmark.cc
index 90e4888..f975989 100644
--- a/icing/index/iterator/doc-hit-info-iterator_benchmark.cc
+++ b/icing/index/iterator/doc-hit-info-iterator_benchmark.cc
@@ -14,15 +14,15 @@
#include <vector>
+#include "testing/base/public/benchmark.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "icing/index/hit/doc-hit-info.h"
#include "icing/index/iterator/doc-hit-info-iterator-and.h"
#include "icing/index/iterator/doc-hit-info-iterator-test-util.h"
#include "icing/index/iterator/doc-hit-info-iterator.h"
#include "icing/schema/section.h"
#include "icing/store/document-id.h"
-#include "testing/base/public/benchmark.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
namespace icing {
namespace lib {
diff --git a/icing/query/query-processor.cc b/icing/query/query-processor.cc
index 0732ed0..1f937fd 100644
--- a/icing/query/query-processor.cc
+++ b/icing/query/query-processor.cc
@@ -46,7 +46,6 @@
#include "icing/tokenization/tokenizer-factory.h"
#include "icing/tokenization/tokenizer.h"
#include "icing/transform/normalizer.h"
-#include "icing/util/clock.h"
#include "icing/util/status-macros.h"
namespace icing {
@@ -105,31 +104,27 @@
const LanguageSegmenter* language_segmenter,
const Normalizer* normalizer,
const DocumentStore* document_store,
- const SchemaStore* schema_store, const Clock* clock) {
+ const SchemaStore* schema_store) {
ICING_RETURN_ERROR_IF_NULL(index);
ICING_RETURN_ERROR_IF_NULL(language_segmenter);
ICING_RETURN_ERROR_IF_NULL(normalizer);
ICING_RETURN_ERROR_IF_NULL(document_store);
ICING_RETURN_ERROR_IF_NULL(schema_store);
- ICING_RETURN_ERROR_IF_NULL(clock);
- return std::unique_ptr<QueryProcessor>(
- new QueryProcessor(index, language_segmenter, normalizer, document_store,
- schema_store, clock));
+ return std::unique_ptr<QueryProcessor>(new QueryProcessor(
+ index, language_segmenter, normalizer, document_store, schema_store));
}
QueryProcessor::QueryProcessor(Index* index,
const LanguageSegmenter* language_segmenter,
const Normalizer* normalizer,
const DocumentStore* document_store,
- const SchemaStore* schema_store,
- const Clock* clock)
+ const SchemaStore* schema_store)
: index_(*index),
language_segmenter_(*language_segmenter),
normalizer_(*normalizer),
document_store_(*document_store),
- schema_store_(*schema_store),
- clock_(*clock) {}
+ schema_store_(*schema_store) {}
DocHitInfoIteratorFilter::Options QueryProcessor::getFilterOptions(
const SearchSpecProto& search_spec) {
@@ -156,7 +151,7 @@
DocHitInfoIteratorFilter::Options options = getFilterOptions(search_spec);
results.root_iterator = std::make_unique<DocHitInfoIteratorFilter>(
std::move(results.root_iterator), &document_store_, &schema_store_,
- &clock_, options);
+ options);
return results;
}
@@ -279,7 +274,7 @@
results.query_term_iterators[normalized_text] =
std::make_unique<DocHitInfoIteratorFilter>(
std::move(term_iterator), &document_store_, &schema_store_,
- &clock_, options);
+ options);
results.query_terms[frames.top().section_restrict].insert(
std::move(normalized_text));
diff --git a/icing/query/query-processor.h b/icing/query/query-processor.h
index 0932ec5..bdf9ef2 100644
--- a/icing/query/query-processor.h
+++ b/icing/query/query-processor.h
@@ -27,7 +27,6 @@
#include "icing/store/document-store.h"
#include "icing/tokenization/language-segmenter.h"
#include "icing/transform/normalizer.h"
-#include "icing/util/clock.h"
namespace icing {
namespace lib {
@@ -47,7 +46,7 @@
static libtextclassifier3::StatusOr<std::unique_ptr<QueryProcessor>> Create(
Index* index, const LanguageSegmenter* language_segmenter,
const Normalizer* normalizer, const DocumentStore* document_store,
- const SchemaStore* schema_store, const Clock* clock);
+ const SchemaStore* schema_store);
struct QueryResults {
std::unique_ptr<DocHitInfoIterator> root_iterator;
@@ -77,7 +76,7 @@
const LanguageSegmenter* language_segmenter,
const Normalizer* normalizer,
const DocumentStore* document_store,
- const SchemaStore* schema_store, const Clock* clock);
+ const SchemaStore* schema_store);
// Parse the query into a one DocHitInfoIterator that represents the root of a
// query tree.
@@ -103,7 +102,6 @@
const Normalizer& normalizer_;
const DocumentStore& document_store_;
const SchemaStore& schema_store_;
- const Clock& clock_;
};
} // namespace lib
diff --git a/icing/query/query-processor_benchmark.cc b/icing/query/query-processor_benchmark.cc
index eb8b7a4..bdd40aa 100644
--- a/icing/query/query-processor_benchmark.cc
+++ b/icing/query/query-processor_benchmark.cc
@@ -147,7 +147,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index.get(), language_segmenter.get(),
normalizer.get(), document_store.get(),
- schema_store.get(), &clock));
+ schema_store.get()));
SearchSpecProto search_spec;
search_spec.set_query(input_string);
@@ -278,7 +278,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index.get(), language_segmenter.get(),
normalizer.get(), document_store.get(),
- schema_store.get(), &clock));
+ schema_store.get()));
const std::string query_string = absl_ports::StrCat(
input_string_a, " ", input_string_b, " ", input_string_c, " ",
@@ -402,7 +402,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index.get(), language_segmenter.get(),
normalizer.get(), document_store.get(),
- schema_store.get(), &clock));
+ schema_store.get()));
SearchSpecProto search_spec;
search_spec.set_query(input_string);
@@ -522,7 +522,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index.get(), language_segmenter.get(),
normalizer.get(), document_store.get(),
- schema_store.get(), &clock));
+ schema_store.get()));
SearchSpecProto search_spec;
search_spec.set_query(input_string);
diff --git a/icing/query/query-processor_test.cc b/icing/query/query-processor_test.cc
index 6ec0a2a..0f49f4d 100644
--- a/icing/query/query-processor_test.cc
+++ b/icing/query/query-processor_test.cc
@@ -32,6 +32,7 @@
#include "icing/proto/schema.pb.h"
#include "icing/proto/search.pb.h"
#include "icing/proto/term.pb.h"
+#include "icing/schema-builder.h"
#include "icing/schema/schema-store.h"
#include "icing/schema/section.h"
#include "icing/store/document-id.h"
@@ -60,30 +61,16 @@
using ::testing::Test;
using ::testing::UnorderedElementsAre;
-SchemaTypeConfigProto* AddSchemaType(SchemaProto* schema,
- std::string schema_type) {
- SchemaTypeConfigProto* type_config = schema->add_types();
- type_config->set_schema_type(schema_type);
- return type_config;
-}
+constexpr PropertyConfigProto_DataType_Code TYPE_STRING =
+ PropertyConfigProto_DataType_Code_STRING;
-void AddIndexedProperty(SchemaTypeConfigProto* type_config, std::string name) {
- PropertyConfigProto* property_config = type_config->add_properties();
- property_config->set_property_name(name);
- property_config->set_data_type(PropertyConfigProto::DataType::STRING);
- property_config->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
- property_config->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::EXACT_ONLY);
- property_config->mutable_string_indexing_config()->set_tokenizer_type(
- StringIndexingConfig::TokenizerType::PLAIN);
-}
+constexpr PropertyConfigProto_Cardinality_Code CARDINALITY_OPTIONAL =
+ PropertyConfigProto_Cardinality_Code_OPTIONAL;
-void AddUnindexedProperty(SchemaTypeConfigProto* type_config,
- std::string name) {
- PropertyConfigProto* property_config = type_config->add_properties();
- property_config->set_property_name(name);
- property_config->set_data_type(PropertyConfigProto::DataType::STRING);
-}
+constexpr StringIndexingConfig_TokenizerType_Code TOKENIZER_PLAIN =
+ StringIndexingConfig_TokenizerType_Code_PLAIN;
+
+constexpr TermMatchType_Code MATCH_EXACT = TermMatchType_Code_EXACT_ONLY;
class QueryProcessorTest : public Test {
protected:
@@ -159,37 +146,33 @@
EXPECT_THAT(
QueryProcessor::Create(/*index=*/nullptr, language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_),
+ schema_store_.get()),
StatusIs(libtextclassifier3::StatusCode::FAILED_PRECONDITION));
EXPECT_THAT(
QueryProcessor::Create(index_.get(), /*language_segmenter=*/nullptr,
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_),
+ schema_store_.get()),
StatusIs(libtextclassifier3::StatusCode::FAILED_PRECONDITION));
EXPECT_THAT(
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
/*normalizer=*/nullptr, document_store_.get(),
- schema_store_.get(), &fake_clock_),
+ schema_store_.get()),
StatusIs(libtextclassifier3::StatusCode::FAILED_PRECONDITION));
- EXPECT_THAT(
- QueryProcessor::Create(index_.get(), language_segmenter_.get(),
- normalizer_.get(), /*document_store=*/nullptr,
- schema_store_.get(), &fake_clock_),
- StatusIs(libtextclassifier3::StatusCode::FAILED_PRECONDITION));
- EXPECT_THAT(QueryProcessor::Create(index_.get(), language_segmenter_.get(),
- normalizer_.get(), document_store_.get(),
- /*schema_store=*/nullptr, &fake_clock_),
+ EXPECT_THAT(QueryProcessor::Create(
+ index_.get(), language_segmenter_.get(), normalizer_.get(),
+ /*document_store=*/nullptr, schema_store_.get()),
StatusIs(libtextclassifier3::StatusCode::FAILED_PRECONDITION));
EXPECT_THAT(QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), /*clock=*/nullptr),
+ /*schema_store=*/nullptr),
StatusIs(libtextclassifier3::StatusCode::FAILED_PRECONDITION));
}
TEST_F(QueryProcessorTest, EmptyGroupMatchAllDocuments) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -221,7 +204,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("()");
@@ -238,8 +221,9 @@
TEST_F(QueryProcessorTest, EmptyQueryMatchAllDocuments) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -271,7 +255,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("");
@@ -288,8 +272,9 @@
TEST_F(QueryProcessorTest, QueryTermNormalized) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -330,7 +315,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("hElLo WORLD");
@@ -363,8 +348,9 @@
TEST_F(QueryProcessorTest, OneTermPrefixMatch) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -402,7 +388,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("he");
@@ -430,8 +416,9 @@
TEST_F(QueryProcessorTest, OneTermExactMatch) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -469,7 +456,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("hello");
@@ -497,8 +484,9 @@
TEST_F(QueryProcessorTest, AndSameTermExactMatch) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -536,7 +524,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("hello hello");
@@ -566,8 +554,9 @@
TEST_F(QueryProcessorTest, AndTwoTermExactMatch) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -608,7 +597,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("hello world");
@@ -640,8 +629,9 @@
TEST_F(QueryProcessorTest, AndSameTermPrefixMatch) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -679,7 +669,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("he he");
@@ -709,8 +699,9 @@
TEST_F(QueryProcessorTest, AndTwoTermPrefixMatch) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -751,7 +742,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("he wo");
@@ -784,8 +775,9 @@
TEST_F(QueryProcessorTest, AndTwoTermPrefixAndExactMatch) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -826,7 +818,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("hello wo");
@@ -859,8 +851,9 @@
TEST_F(QueryProcessorTest, OrTwoTermExactMatch) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -906,7 +899,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("hello OR world");
@@ -947,8 +940,9 @@
TEST_F(QueryProcessorTest, OrTwoTermPrefixMatch) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -994,7 +988,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("he OR wo");
@@ -1034,8 +1028,9 @@
TEST_F(QueryProcessorTest, OrTwoTermPrefixAndExactMatch) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -1080,7 +1075,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("hello OR wo");
@@ -1120,8 +1115,9 @@
TEST_F(QueryProcessorTest, CombinedAndOrTerms) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -1179,7 +1175,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
{
// OR gets precedence over AND, this is parsed as ((puppy OR kitten) AND
@@ -1305,8 +1301,9 @@
TEST_F(QueryProcessorTest, OneGroup) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -1356,7 +1353,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
// Without grouping, this would be parsed as ((puppy OR kitten) AND foo) and
// no documents would match. But with grouping, Document 1 matches puppy
@@ -1380,8 +1377,9 @@
TEST_F(QueryProcessorTest, TwoGroups) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -1430,7 +1428,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
// Without grouping, this would be parsed as (puppy AND (dog OR kitten) AND
// cat) and wouldn't match any documents. But with grouping, Document 1
@@ -1457,8 +1455,9 @@
TEST_F(QueryProcessorTest, ManyLevelNestedGrouping) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -1508,7 +1507,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
// Without grouping, this would be parsed as ((puppy OR kitten) AND foo) and
// no documents would match. But with grouping, Document 1 matches puppy
@@ -1532,8 +1531,9 @@
TEST_F(QueryProcessorTest, OneLevelNestedGrouping) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -1583,7 +1583,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
// Document 1 will match puppy and Document 2 matches (kitten AND (cat))
SearchSpecProto search_spec;
@@ -1608,8 +1608,9 @@
TEST_F(QueryProcessorTest, ExcludeTerm) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -1652,7 +1653,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("-hello");
@@ -1672,8 +1673,9 @@
TEST_F(QueryProcessorTest, ExcludeNonexistentTerm) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -1715,7 +1717,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("-foo");
@@ -1734,8 +1736,9 @@
TEST_F(QueryProcessorTest, ExcludeAnd) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -1785,7 +1788,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
{
SearchSpecProto search_spec;
@@ -1823,8 +1826,9 @@
TEST_F(QueryProcessorTest, ExcludeOr) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -1874,7 +1878,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
{
SearchSpecProto search_spec;
@@ -1918,8 +1922,9 @@
TEST_F(QueryProcessorTest, DeletedFilter) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -1970,7 +1975,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("animal");
@@ -1991,8 +1996,9 @@
TEST_F(QueryProcessorTest, NamespaceFilter) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -2042,7 +2048,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("animal");
@@ -2064,9 +2070,11 @@
TEST_F(QueryProcessorTest, SchemaTypeFilter) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
- AddSchemaType(&schema, "message");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -2112,7 +2120,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("animal");
@@ -2134,11 +2142,15 @@
TEST_F(QueryProcessorTest, SectionFilterForOneDocument) {
// Create the schema and document store
- SchemaProto schema;
- SchemaTypeConfigProto* email_type = AddSchemaType(&schema, "email");
-
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("subject")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
// First and only indexed property, so it gets a section_id of 0
- AddIndexedProperty(email_type, "subject");
int subject_section_id = 0;
ICING_ASSERT_OK_AND_ASSIGN(
@@ -2174,7 +2186,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
// Create a section filter '<section name>:<query term>'
@@ -2196,18 +2208,31 @@
TEST_F(QueryProcessorTest, SectionFilterAcrossSchemaTypes) {
// Create the schema and document store
- SchemaProto schema;
- SchemaTypeConfigProto* email_type = AddSchemaType(&schema, "email");
- // SectionIds are assigned in ascending order per schema type,
- // alphabetically.
- AddIndexedProperty(email_type, "a"); // Section "a" would get sectionId 0
- AddIndexedProperty(email_type, "foo");
- int email_foo_section_id = 1;
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType("email")
+ // Section "a" would get sectionId 0
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("a")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL))
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("foo")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .AddType(SchemaTypeConfigBuilder().SetType("message").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("foo")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
- SchemaTypeConfigProto* message_type = AddSchemaType(&schema, "message");
// SectionIds are assigned in ascending order per schema type,
// alphabetically.
- AddIndexedProperty(message_type, "foo");
+ int email_foo_section_id = 1;
int message_foo_section_id = 0;
ICING_ASSERT_OK_AND_ASSIGN(
@@ -2253,7 +2278,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
// Create a section filter '<section name>:<query term>'
@@ -2277,18 +2302,20 @@
}
TEST_F(QueryProcessorTest, SectionFilterWithinSchemaType) {
- // Create the schema and document store
- SchemaProto schema;
- SchemaTypeConfigProto* email_type = AddSchemaType(&schema, "email");
- // SectionIds are assigned in ascending order per schema type,
- // alphabetically.
- AddIndexedProperty(email_type, "foo");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("foo")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .AddType(SchemaTypeConfigBuilder().SetType("message").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("foo")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
int email_foo_section_id = 0;
-
- SchemaTypeConfigProto* message_type = AddSchemaType(&schema, "message");
- // SectionIds are assigned in ascending order per schema type,
- // alphabetically.
- AddIndexedProperty(message_type, "foo");
int message_foo_section_id = 0;
ICING_ASSERT_OK_AND_ASSIGN(
@@ -2334,7 +2361,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
// Create a section filter '<section name>:<query term>', but only look
@@ -2359,17 +2386,20 @@
TEST_F(QueryProcessorTest, SectionFilterRespectsDifferentSectionIds) {
// Create the schema and document store
- SchemaProto schema;
- SchemaTypeConfigProto* email_type = AddSchemaType(&schema, "email");
- // SectionIds are assigned in ascending order per schema type,
- // alphabetically.
- AddIndexedProperty(email_type, "foo");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("foo")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .AddType(SchemaTypeConfigBuilder().SetType("message").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("bar")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
int email_foo_section_id = 0;
-
- SchemaTypeConfigProto* message_type = AddSchemaType(&schema, "message");
- // SectionIds are assigned in ascending order per schema type,
- // alphabetically.
- AddIndexedProperty(message_type, "bar");
int message_foo_section_id = 0;
ICING_ASSERT_OK_AND_ASSIGN(
@@ -2417,7 +2447,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
// Create a section filter '<section name>:<query term>', but only look
@@ -2441,8 +2471,9 @@
TEST_F(QueryProcessorTest, NonexistentSectionFilterReturnsEmptyResults) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -2477,7 +2508,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
// Create a section filter '<section name>:<query term>', but only look
@@ -2499,9 +2530,17 @@
TEST_F(QueryProcessorTest, UnindexedSectionFilterReturnsEmptyResults) {
// Create the schema and document store
- SchemaProto schema;
- SchemaTypeConfigProto* email_type = AddSchemaType(&schema, "email");
- AddUnindexedProperty(email_type, "foo");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType("email")
+ // Add an unindexed property so we generate section
+ // metadata on it
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("foo")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -2536,7 +2575,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
// Create a section filter '<section name>:<query term>', but only look
@@ -2557,17 +2596,20 @@
TEST_F(QueryProcessorTest, SectionFilterTermAndUnrestrictedTerm) {
// Create the schema and document store
- SchemaProto schema;
- SchemaTypeConfigProto* email_type = AddSchemaType(&schema, "email");
- // SectionIds are assigned in ascending order per schema type,
- // alphabetically.
- AddIndexedProperty(email_type, "foo");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("foo")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .AddType(SchemaTypeConfigBuilder().SetType("message").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("foo")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
int email_foo_section_id = 0;
-
- SchemaTypeConfigProto* message_type = AddSchemaType(&schema, "message");
- // SectionIds are assigned in ascending order per schema type,
- // alphabetically.
- AddIndexedProperty(message_type, "foo");
int message_foo_section_id = 0;
ICING_ASSERT_OK_AND_ASSIGN(
@@ -2615,7 +2657,7 @@
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
// Create a section filter '<section name>:<query term>'
@@ -2641,27 +2683,34 @@
TEST_F(QueryProcessorTest, DocumentBeforeTtlNotFilteredOut) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
SchemaStore::Create(&filesystem_, test_dir_, &fake_clock_));
ASSERT_THAT(schema_store_->SetSchema(schema), IsOk());
+ // Arbitrary value, just has to be less than the document's creation
+ // timestamp + ttl
+ FakeClock fake_clock;
+ fake_clock.SetSystemTimeMilliseconds(50);
+
ICING_ASSERT_OK_AND_ASSIGN(
DocumentStore::CreateResult create_result,
- DocumentStore::Create(&filesystem_, store_dir_, &fake_clock_,
+ DocumentStore::Create(&filesystem_, store_dir_, &fake_clock,
schema_store_.get()));
document_store_ = std::move(create_result.document_store);
- ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id,
- document_store_->Put(DocumentBuilder()
- .SetKey("namespace", "1")
- .SetSchema("email")
- .SetCreationTimestampMs(0)
- .SetTtlMs(100)
- .Build()));
+ ICING_ASSERT_OK_AND_ASSIGN(
+ DocumentId document_id,
+ document_store_->Put(DocumentBuilder()
+ .SetKey("namespace", "1")
+ .SetSchema("email")
+ .SetCreationTimestampMs(10)
+ .SetTtlMs(100)
+ .Build()));
// Populate the index
int section_id = 0;
@@ -2671,17 +2720,12 @@
AddTokenToIndex(document_id, section_id, term_match_type, "hello"),
IsOk());
- // Arbitrary value, just has to be less than the document's creation
- // timestamp + ttl
- FakeClock fake_clock;
- fake_clock.SetSystemTimeMilliseconds(50);
-
// Perform query
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock_));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("hello");
@@ -2698,27 +2742,34 @@
TEST_F(QueryProcessorTest, DocumentPastTtlFilteredOut) {
// Create the schema and document store
- SchemaProto schema;
- AddSchemaType(&schema, "email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
SchemaStore::Create(&filesystem_, test_dir_, &fake_clock_));
ASSERT_THAT(schema_store_->SetSchema(schema), IsOk());
+ // Arbitrary value, just has to be greater than the document's creation
+ // timestamp + ttl
+ FakeClock fake_clock;
+ fake_clock.SetSystemTimeMilliseconds(200);
+
ICING_ASSERT_OK_AND_ASSIGN(
DocumentStore::CreateResult create_result,
- DocumentStore::Create(&filesystem_, store_dir_, &fake_clock_,
+ DocumentStore::Create(&filesystem_, store_dir_, &fake_clock,
schema_store_.get()));
document_store_ = std::move(create_result.document_store);
- ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id,
- document_store_->Put(DocumentBuilder()
- .SetKey("namespace", "1")
- .SetSchema("email")
- .SetCreationTimestampMs(0)
- .SetTtlMs(100)
- .Build()));
+ ICING_ASSERT_OK_AND_ASSIGN(
+ DocumentId document_id,
+ document_store_->Put(DocumentBuilder()
+ .SetKey("namespace", "1")
+ .SetSchema("email")
+ .SetCreationTimestampMs(50)
+ .SetTtlMs(100)
+ .Build()));
// Populate the index
int section_id = 0;
@@ -2728,17 +2779,12 @@
AddTokenToIndex(document_id, section_id, term_match_type, "hello"),
IsOk());
- // Arbitrary value, just has to be greater than the document's creation
- // timestamp + ttl
- FakeClock fake_clock;
- fake_clock.SetSystemTimeMilliseconds(200);
-
// Perform query
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<QueryProcessor> query_processor,
QueryProcessor::Create(index_.get(), language_segmenter_.get(),
normalizer_.get(), document_store_.get(),
- schema_store_.get(), &fake_clock));
+ schema_store_.get()));
SearchSpecProto search_spec;
search_spec.set_query("hello");
diff --git a/icing/schema/schema-store_test.cc b/icing/schema/schema-store_test.cc
index d97948f..69663b5 100644
--- a/icing/schema/schema-store_test.cc
+++ b/icing/schema/schema-store_test.cc
@@ -25,6 +25,7 @@
#include "icing/portable/equals-proto.h"
#include "icing/proto/document.pb.h"
#include "icing/proto/schema.pb.h"
+#include "icing/schema-builder.h"
#include "icing/schema/schema-util.h"
#include "icing/schema/section-manager.h"
#include "icing/schema/section.h"
@@ -46,34 +47,33 @@
using ::testing::Not;
using ::testing::Pointee;
-PropertyConfigProto CreateProperty(
- std::string_view name, PropertyConfigProto::DataType::Code datatype,
- PropertyConfigProto::Cardinality::Code cardinality,
- TermMatchType::Code match_type,
- StringIndexingConfig::TokenizerType::Code tokenizer_type) {
- PropertyConfigProto property;
- property.set_property_name(std::string(name));
- property.set_data_type(datatype);
- property.set_cardinality(cardinality);
- property.mutable_string_indexing_config()->set_term_match_type(match_type);
- property.mutable_string_indexing_config()->set_tokenizer_type(tokenizer_type);
- return property;
-}
+constexpr PropertyConfigProto_Cardinality_Code CARDINALITY_OPTIONAL =
+ PropertyConfigProto_Cardinality_Code_OPTIONAL;
+
+constexpr StringIndexingConfig_TokenizerType_Code TOKENIZER_PLAIN =
+ StringIndexingConfig_TokenizerType_Code_PLAIN;
+
+constexpr TermMatchType_Code MATCH_EXACT = TermMatchType_Code_EXACT_ONLY;
+
+constexpr PropertyConfigProto_DataType_Code TYPE_STRING =
+ PropertyConfigProto_DataType_Code_STRING;
+constexpr PropertyConfigProto_DataType_Code TYPE_DOUBLE =
+ PropertyConfigProto_DataType_Code_DOUBLE;
class SchemaStoreTest : public ::testing::Test {
protected:
SchemaStoreTest() : test_dir_(GetTestTempDir() + "/icing") {
filesystem_.CreateDirectoryRecursively(test_dir_.c_str());
- auto type = schema_.add_types();
- type->set_schema_type("email");
-
- // Add an indexed property so we generate section metadata on it
- auto property = type->add_properties();
- *property = CreateProperty("subject", PropertyConfigProto::DataType::STRING,
- PropertyConfigProto::Cardinality::OPTIONAL,
- TermMatchType::EXACT_ONLY,
- StringIndexingConfig::TokenizerType::PLAIN);
+ schema_ =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ // Add an indexed property so we generate section metadata on it
+ PropertyConfigBuilder()
+ .SetName("subject")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
}
void TearDown() override {
@@ -111,9 +111,10 @@
// "Corrupt" the ground truth schema by adding new data to it. This will mess
// up the checksum of the schema store
- SchemaProto corrupt_schema;
- auto type = corrupt_schema.add_types();
- type->set_schema_type("corrupted");
+ SchemaProto corrupt_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("corrupted"))
+ .Build();
const std::string schema_file = absl_ports::StrCat(test_dir_, "/schema.pb");
const std::string serialized_schema = corrupt_schema.SerializeAsString();
@@ -358,9 +359,9 @@
std::unique_ptr<SchemaStore> schema_store,
SchemaStore::Create(&filesystem_, test_dir_, &fake_clock_));
- SchemaProto schema;
- auto type = schema.add_types();
- type->set_schema_type("email");
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
// Set it for the first time
SchemaStore::SetSchemaResult result;
@@ -372,8 +373,9 @@
EXPECT_THAT(*actual_schema, EqualsProto(schema));
// Add a type, shouldn't affect the index or cached SchemaTypeIds
- type = schema.add_types();
- type->set_schema_type("new_type");
+ schema = SchemaBuilder(schema)
+ .AddType(SchemaTypeConfigBuilder().SetType("new_type"))
+ .Build();
// Set the compatible schema
EXPECT_THAT(schema_store->SetSchema(schema),
@@ -387,11 +389,11 @@
std::unique_ptr<SchemaStore> schema_store,
SchemaStore::Create(&filesystem_, test_dir_, &fake_clock_));
- SchemaProto schema;
- auto type = schema.add_types();
- type->set_schema_type("email");
- type = schema.add_types();
- type->set_schema_type("message");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
// Set it for the first time
SchemaStore::SetSchemaResult result;
@@ -408,9 +410,9 @@
schema_store->GetSchemaTypeId("message"));
// Remove "email" type, this also changes previous SchemaTypeIds
- schema.Clear();
- type = schema.add_types();
- type->set_schema_type("message");
+ schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
SchemaStore::SetSchemaResult incompatible_result;
incompatible_result.success = false;
@@ -443,11 +445,11 @@
std::unique_ptr<SchemaStore> schema_store,
SchemaStore::Create(&filesystem_, test_dir_, &fake_clock_));
- SchemaProto schema;
- auto type = schema.add_types();
- type->set_schema_type("email");
- type = schema.add_types();
- type->set_schema_type("message");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
// Set it for the first time
SchemaStore::SetSchemaResult result;
@@ -459,11 +461,10 @@
EXPECT_THAT(*actual_schema, EqualsProto(schema));
// Reorder the types
- schema.clear_types();
- type = schema.add_types();
- type->set_schema_type("message");
- type = schema.add_types();
- type->set_schema_type("email");
+ schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
// Since we assign SchemaTypeIds based on order in the SchemaProto, this will
// cause SchemaTypeIds to change
@@ -483,15 +484,15 @@
std::unique_ptr<SchemaStore> schema_store,
SchemaStore::Create(&filesystem_, test_dir_, &fake_clock_));
- SchemaProto schema;
- auto type = schema.add_types();
- type->set_schema_type("email");
-
- // Add an unindexed property
- auto property = type->add_properties();
- property->set_property_name("subject");
- property->set_data_type(PropertyConfigProto::DataType::STRING);
- property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ // Add an unindexed property
+ PropertyConfigBuilder()
+ .SetName("subject")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
// Set it for the first time
SchemaStore::SetSchemaResult result;
@@ -503,11 +504,13 @@
EXPECT_THAT(*actual_schema, EqualsProto(schema));
// Make a previously unindexed property indexed
- property = schema.mutable_types(0)->mutable_properties(0);
- property->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::EXACT_ONLY);
- property->mutable_string_indexing_config()->set_tokenizer_type(
- StringIndexingConfig::TokenizerType::PLAIN);
+ schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("subject")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
// With a new indexed property, we'll need to reindex
result.index_incompatible = true;
@@ -524,15 +527,15 @@
std::unique_ptr<SchemaStore> schema_store,
SchemaStore::Create(&filesystem_, test_dir_, &fake_clock_));
- SchemaProto schema;
- auto type = schema.add_types();
- type->set_schema_type("email");
-
- // Add a STRING property
- auto property = type->add_properties();
- property->set_property_name("subject");
- property->set_data_type(PropertyConfigProto::DataType::STRING);
- property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ // Add a STRING property
+ PropertyConfigBuilder()
+ .SetName("subject")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
// Set it for the first time
SchemaStore::SetSchemaResult result;
@@ -547,8 +550,14 @@
schema_store->GetSchemaTypeId("email"));
// Make a previously STRING property into DOUBLE
- property = schema.mutable_types(0)->mutable_properties(0);
- property->set_data_type(PropertyConfigProto::DataType::DOUBLE);
+ schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ // Add a STRING property
+ PropertyConfigBuilder()
+ .SetName("subject")
+ .SetDataType(TYPE_DOUBLE)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
SchemaStore::SetSchemaResult incompatible_result;
incompatible_result.success = false;
@@ -614,9 +623,8 @@
std::unique_ptr<SchemaStore> schema_store,
SchemaStore::Create(&filesystem_, test_dir_, &fake_clock_));
- SchemaProto foo_schema;
- auto type_config = foo_schema.add_types();
- type_config->set_schema_type("foo");
+ SchemaProto foo_schema =
+ SchemaBuilder().AddType(SchemaTypeConfigBuilder().SetType("foo")).Build();
ICING_EXPECT_OK(schema_store->SetSchema(foo_schema));
@@ -631,9 +639,8 @@
std::unique_ptr<SchemaStore> schema_store,
SchemaStore::Create(&filesystem_, test_dir_, &fake_clock_));
- SchemaProto foo_schema;
- auto type_config = foo_schema.add_types();
- type_config->set_schema_type("foo");
+ SchemaProto foo_schema =
+ SchemaBuilder().AddType(SchemaTypeConfigBuilder().SetType("foo")).Build();
ICING_EXPECT_OK(schema_store->SetSchema(foo_schema));
@@ -652,20 +659,19 @@
std::unique_ptr<SchemaStore> schema_store,
SchemaStore::Create(&filesystem_, test_dir_, &fake_clock_));
- SchemaProto foo_schema;
- auto type_config = foo_schema.add_types();
- type_config->set_schema_type("foo");
+ SchemaProto foo_schema =
+ SchemaBuilder().AddType(SchemaTypeConfigBuilder().SetType("foo")).Build();
ICING_EXPECT_OK(schema_store->SetSchema(foo_schema));
ICING_ASSERT_OK_AND_ASSIGN(Crc32 checksum, schema_store->ComputeChecksum());
// Modifying the SchemaStore changes the checksum
- SchemaProto foo_bar_schema;
- type_config = foo_bar_schema.add_types();
- type_config->set_schema_type("foo");
- type_config = foo_bar_schema.add_types();
- type_config->set_schema_type("bar");
+ SchemaProto foo_bar_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("foo"))
+ .AddType(SchemaTypeConfigBuilder().SetType("bar"))
+ .Build();
ICING_EXPECT_OK(schema_store->SetSchema(foo_bar_schema));
@@ -686,9 +692,8 @@
std::unique_ptr<SchemaStore> schema_store,
SchemaStore::Create(&filesystem_, test_dir_, &fake_clock_));
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("foo");
+ SchemaProto schema =
+ SchemaBuilder().AddType(SchemaTypeConfigBuilder().SetType("foo")).Build();
ICING_EXPECT_OK(schema_store->SetSchema(schema));
@@ -700,8 +705,9 @@
EXPECT_THAT(*actual_schema, EqualsProto(schema));
// Modify the schema so that something different is persisted next time
- type_config = schema.add_types();
- type_config->set_schema_type("bar");
+ schema = SchemaBuilder(schema)
+ .AddType(SchemaTypeConfigBuilder().SetType("bar"))
+ .Build();
ICING_EXPECT_OK(schema_store->SetSchema(schema));
// Should also persist on destruction
@@ -721,49 +727,36 @@
// Create a schema with two types: one simple type and one type that uses all
// 16 sections.
- SchemaProto schema;
- auto type = schema.add_types();
- type->set_schema_type("email");
- PropertyConfigProto prop = CreateProperty(
- "subject", PropertyConfigProto::DataType::STRING,
- PropertyConfigProto::Cardinality::OPTIONAL, TermMatchType::EXACT_ONLY,
- StringIndexingConfig::TokenizerType::PLAIN);
- *type->add_properties() = prop;
-
- type = schema.add_types();
- type->set_schema_type("fullSectionsType");
- prop.set_property_name("prop0");
- *type->add_properties() = prop;
- prop.set_property_name("prop1");
- *type->add_properties() = prop;
- prop.set_property_name("prop2");
- *type->add_properties() = prop;
- prop.set_property_name("prop3");
- *type->add_properties() = prop;
- prop.set_property_name("prop4");
- *type->add_properties() = prop;
- prop.set_property_name("prop5");
- *type->add_properties() = prop;
- prop.set_property_name("prop6");
- *type->add_properties() = prop;
- prop.set_property_name("prop7");
- *type->add_properties() = prop;
- prop.set_property_name("prop8");
- *type->add_properties() = prop;
- prop.set_property_name("prop9");
- *type->add_properties() = prop;
- prop.set_property_name("prop10");
- *type->add_properties() = prop;
- prop.set_property_name("prop11");
- *type->add_properties() = prop;
- prop.set_property_name("prop12");
- *type->add_properties() = prop;
- prop.set_property_name("prop13");
- *type->add_properties() = prop;
- prop.set_property_name("prop14");
- *type->add_properties() = prop;
- prop.set_property_name("prop15");
- *type->add_properties() = prop;
+ PropertyConfigProto prop =
+ PropertyConfigBuilder()
+ .SetName("subject")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)
+ .Build();
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ PropertyConfigBuilder(prop)))
+ .AddType(
+ SchemaTypeConfigBuilder()
+ .SetType("fullSectionsType")
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop0"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop1"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop2"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop3"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop4"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop5"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop6"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop7"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop8"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop9"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop10"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop11"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop12"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop13"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop14"))
+ .AddProperty(PropertyConfigBuilder(prop).SetName("prop15")))
+ .Build();
SchemaStore::SetSchemaResult result;
result.success = true;
diff --git a/icing/schema/schema-util_test.cc b/icing/schema/schema-util_test.cc
index 61a861c..a2fc8d9 100644
--- a/icing/schema/schema-util_test.cc
+++ b/icing/schema/schema-util_test.cc
@@ -22,6 +22,7 @@
#include "gtest/gtest.h"
#include "icing/proto/schema.pb.h"
#include "icing/proto/term.pb.h"
+#include "icing/schema-builder.h"
#include "icing/testing/common-matchers.h"
namespace icing {
@@ -35,285 +36,310 @@
constexpr char kEmailType[] = "EmailMessage";
constexpr char kPersonType[] = "Person";
-class SchemaUtilTest : public ::testing::Test {
- protected:
- SchemaProto schema_proto_;
+constexpr PropertyConfigProto_DataType_Code TYPE_DOCUMENT =
+ PropertyConfigProto_DataType_Code_DOCUMENT;
+constexpr PropertyConfigProto_DataType_Code TYPE_STRING =
+ PropertyConfigProto_DataType_Code_STRING;
+constexpr PropertyConfigProto_DataType_Code TYPE_INT =
+ PropertyConfigProto_DataType_Code_INT64;
+constexpr PropertyConfigProto_DataType_Code TYPE_DOUBLE =
+ PropertyConfigProto_DataType_Code_DOUBLE;
- static SchemaTypeConfigProto CreateSchemaTypeConfig(
- const std::string_view schema_type,
- const std::string_view nested_schema_type = "") {
- SchemaTypeConfigProto type;
- type.set_schema_type(std::string(schema_type));
+constexpr PropertyConfigProto_Cardinality_Code CARDINALITY_UNKNOWN =
+ PropertyConfigProto_Cardinality_Code_UNKNOWN;
+constexpr PropertyConfigProto_Cardinality_Code CARDINALITY_REQUIRED =
+ PropertyConfigProto_Cardinality_Code_REQUIRED;
+constexpr PropertyConfigProto_Cardinality_Code CARDINALITY_OPTIONAL =
+ PropertyConfigProto_Cardinality_Code_OPTIONAL;
+constexpr PropertyConfigProto_Cardinality_Code CARDINALITY_REPEATED =
+ PropertyConfigProto_Cardinality_Code_REPEATED;
- auto string_property = type.add_properties();
- string_property->set_property_name("string");
- string_property->set_data_type(PropertyConfigProto::DataType::STRING);
- string_property->set_cardinality(
- PropertyConfigProto::Cardinality::REQUIRED);
+constexpr StringIndexingConfig_TokenizerType_Code TOKENIZER_NONE =
+ StringIndexingConfig_TokenizerType_Code_NONE;
+constexpr StringIndexingConfig_TokenizerType_Code TOKENIZER_PLAIN =
+ StringIndexingConfig_TokenizerType_Code_PLAIN;
- auto int_property = type.add_properties();
- int_property->set_property_name("int");
- int_property->set_data_type(PropertyConfigProto::DataType::INT64);
- int_property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
+constexpr TermMatchType_Code MATCH_UNKNOWN = TermMatchType_Code_UNKNOWN;
+constexpr TermMatchType_Code MATCH_EXACT = TermMatchType_Code_EXACT_ONLY;
+constexpr TermMatchType_Code MATCH_PREFIX = TermMatchType_Code_PREFIX;
- auto double_property = type.add_properties();
- double_property->set_property_name("double");
- double_property->set_data_type(PropertyConfigProto::DataType::DOUBLE);
- double_property->set_cardinality(
- PropertyConfigProto::Cardinality::REPEATED);
-
- auto bool_property = type.add_properties();
- bool_property->set_property_name("boolean");
- bool_property->set_data_type(PropertyConfigProto::DataType::BOOLEAN);
- bool_property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
-
- auto bytes_property = type.add_properties();
- bytes_property->set_property_name("bytes");
- bytes_property->set_data_type(PropertyConfigProto::DataType::BYTES);
- bytes_property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
-
- if (!nested_schema_type.empty()) {
- auto document_property = type.add_properties();
- document_property->set_property_name("document");
- document_property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- document_property->set_cardinality(
- PropertyConfigProto::Cardinality::REPEATED);
- document_property->set_schema_type(std::string(nested_schema_type));
- }
-
- return type;
- }
-};
-
-TEST_F(SchemaUtilTest, EmptySchemaProtoIsValid) {
- ICING_ASSERT_OK(SchemaUtil::Validate(schema_proto_));
+TEST(SchemaUtilTest, EmptySchemaProtoIsValid) {
+ SchemaProto schema;
+ ICING_ASSERT_OK(SchemaUtil::Validate(schema));
}
-TEST_F(SchemaUtilTest, Valid_Nested) {
- auto email_type = schema_proto_.add_types();
- *email_type = CreateSchemaTypeConfig(kEmailType, kPersonType);
+TEST(SchemaUtilTest, Valid_Nested) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("subject")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("sender")
+ .SetDataTypeDocument(
+ kPersonType,
+ /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kPersonType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("name")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
- auto person_type = schema_proto_.add_types();
- *person_type = CreateSchemaTypeConfig(kPersonType);
-
- ICING_ASSERT_OK(SchemaUtil::Validate(schema_proto_));
+ ICING_ASSERT_OK(SchemaUtil::Validate(schema));
}
-TEST_F(SchemaUtilTest, ClearedPropertyConfigsIsValid) {
+TEST(SchemaUtilTest, ClearedPropertyConfigsIsValid) {
// No property fields is technically ok, but probably not realistic.
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
- type->clear_properties();
-
- ICING_ASSERT_OK(SchemaUtil::Validate(schema_proto_));
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType(kEmailType))
+ .Build();
+ ICING_ASSERT_OK(SchemaUtil::Validate(schema));
}
-TEST_F(SchemaUtilTest, ClearedSchemaTypeIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
- type->clear_schema_type();
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+TEST(SchemaUtilTest, ClearedSchemaTypeIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder().AddType(SchemaTypeConfigBuilder()).Build();
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
-TEST_F(SchemaUtilTest, EmptySchemaTypeIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
- type->set_schema_type("");
+TEST(SchemaUtilTest, EmptySchemaTypeIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder().AddType(SchemaTypeConfigBuilder().SetType("")).Build();
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
-TEST_F(SchemaUtilTest, AnySchemaTypeOk) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
- type->set_schema_type("abc123!@#$%^&*()_-+=[{]}|\\;:'\",<.>?ä½ å¥½");
+TEST(SchemaUtilTest, AnySchemaTypeOk) {
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType(
+ "abc123!@#$%^&*()_-+=[{]}|\\;:'\",<.>?ä½ å¥½"))
+ .Build();
- ICING_ASSERT_OK(SchemaUtil::Validate(schema_proto_));
+ ICING_ASSERT_OK(SchemaUtil::Validate(schema));
}
-TEST_F(SchemaUtilTest, ClearedPropertyNameIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto property = type->add_properties();
- property->clear_property_name();
- property->set_data_type(PropertyConfigProto::DataType::STRING);
- property->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+TEST(SchemaUtilTest, ClearedPropertyNameIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("foo")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
+ schema.mutable_types(0)->mutable_properties(0)->clear_property_name();
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
-TEST_F(SchemaUtilTest, EmptyPropertyNameIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
+TEST(SchemaUtilTest, EmptyPropertyNameIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
- auto property = type->add_properties();
- property->set_property_name("");
- property->set_data_type(PropertyConfigProto::DataType::STRING);
- property->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
-TEST_F(SchemaUtilTest, NonAlphanumericPropertyNameIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
+TEST(SchemaUtilTest, NonAlphanumericPropertyNameIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("a_b")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
- auto property = type->add_properties();
- property->set_property_name("_");
- property->set_data_type(PropertyConfigProto::DataType::STRING);
- property->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
-TEST_F(SchemaUtilTest, AlphanumericPropertyNameOk) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
+TEST(SchemaUtilTest, AlphanumericPropertyNameOk) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("abc123")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
- auto property = type->add_properties();
- property->set_property_name("abc123");
- property->set_data_type(PropertyConfigProto::DataType::STRING);
- property->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
-
- ICING_ASSERT_OK(SchemaUtil::Validate(schema_proto_));
+ ICING_ASSERT_OK(SchemaUtil::Validate(schema));
}
-TEST_F(SchemaUtilTest, DuplicatePropertyNameIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto first_property = type->add_properties();
- first_property->set_property_name("DuplicatedProperty");
- first_property->set_data_type(PropertyConfigProto::DataType::STRING);
- first_property->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
-
- auto second_property = type->add_properties();
- second_property->set_property_name("DuplicatedProperty");
- second_property->set_data_type(PropertyConfigProto::DataType::STRING);
- second_property->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+TEST(SchemaUtilTest, DuplicatePropertyNameIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("DuplicatedProperty")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("DuplicatedProperty")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::ALREADY_EXISTS));
}
-TEST_F(SchemaUtilTest, ClearedDataTypeIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto property = type->add_properties();
- property->set_property_name("NewProperty");
- property->clear_data_type();
- property->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+TEST(SchemaUtilTest, ClearedDataTypeIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NewProperty")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
+ schema.mutable_types(0)->mutable_properties(0)->clear_data_type();
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
-TEST_F(SchemaUtilTest, UnknownDataTypeIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto property = type->add_properties();
- property->set_property_name("NewProperty");
- property->set_data_type(PropertyConfigProto::DataType::UNKNOWN);
- property->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+TEST(SchemaUtilTest, UnknownDataTypeIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(
+ SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("NewProperty")
+ .SetDataType(PropertyConfigProto::DataType::UNKNOWN)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
-TEST_F(SchemaUtilTest, ClearedCardinalityIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto property = type->add_properties();
- property->set_property_name("NewProperty");
- property->set_data_type(PropertyConfigProto::DataType::STRING);
- property->clear_cardinality();
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+TEST(SchemaUtilTest, ClearedCardinalityIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NewProperty")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
+ schema.mutable_types(0)->mutable_properties(0)->clear_cardinality();
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
-TEST_F(SchemaUtilTest, UnknownCardinalityIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto property = type->add_properties();
- property->set_property_name("NewProperty");
- property->set_data_type(PropertyConfigProto::DataType::STRING);
- property->set_cardinality(PropertyConfigProto::Cardinality::UNKNOWN);
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+TEST(SchemaUtilTest, UnknownCardinalityIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NewProperty")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_UNKNOWN)))
+ .Build();
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
-TEST_F(SchemaUtilTest, ClearedPropertySchemaTypeIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto property = type->add_properties();
- property->set_property_name("NewProperty");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
- property->clear_schema_type();
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+TEST(SchemaUtilTest, ClearedPropertySchemaTypeIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NewProperty")
+ .SetDataType(TYPE_DOCUMENT)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
-TEST_F(SchemaUtilTest, Invalid_EmptyPropertySchemaType) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
+TEST(SchemaUtilTest, Invalid_EmptyPropertySchemaType) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NewProperty")
+ .SetDataTypeDocument(
+ /*schema_type=*/"",
+ /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
- auto property = type->add_properties();
- property->set_property_name("NewProperty");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
- property->set_schema_type("");
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
-TEST_F(SchemaUtilTest, NoMatchingSchemaTypeIsInvalid) {
- auto type = schema_proto_.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
+TEST(SchemaUtilTest, NoMatchingSchemaTypeIsInvalid) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NewProperty")
+ .SetDataTypeDocument(
+ /*schema_type=*/"NewSchemaType",
+ /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
- auto property = type->add_properties();
- property->set_property_name("NewProperty");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
- property->set_schema_type("NewSchemaType");
-
- ASSERT_THAT(SchemaUtil::Validate(schema_proto_),
+ ASSERT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::UNKNOWN,
HasSubstr("Undefined 'schema_type'")));
}
-TEST_F(SchemaUtilTest, NewOptionalPropertyIsCompatible) {
+TEST(SchemaUtilTest, NewOptionalPropertyIsCompatible) {
// Configure old schema
- SchemaProto old_schema;
- auto type = old_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
+ SchemaProto old_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("prop1")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
// Configure new schema with an optional field, not considered incompatible
// since it's fine if old data doesn't have this optional field
- SchemaProto new_schema_with_optional;
- type = new_schema_with_optional.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto property = type->add_properties();
- property->set_property_name("NewOptional");
- property->set_data_type(PropertyConfigProto::DataType::DOUBLE);
- property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
+ SchemaProto new_schema_with_optional =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("prop1")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NewOptional")
+ .SetDataType(TYPE_DOUBLE)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
SchemaUtil::SchemaDelta schema_delta;
EXPECT_THAT(SchemaUtil::ComputeCompatibilityDelta(old_schema,
@@ -321,22 +347,33 @@
Eq(schema_delta));
}
-TEST_F(SchemaUtilTest, NewRequiredPropertyIsIncompatible) {
+TEST(SchemaUtilTest, NewRequiredPropertyIsIncompatible) {
// Configure old schema
- SchemaProto old_schema;
- auto type = old_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
+ SchemaProto old_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("prop1")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
// Configure new schema with a required field, considered incompatible since
// old data won't have this required field
- SchemaProto new_schema_with_required;
- type = new_schema_with_required.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto property = type->add_properties();
- property->set_property_name("NewRequired");
- property->set_data_type(PropertyConfigProto::DataType::DOUBLE);
- property->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
+ SchemaProto new_schema_with_required =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("prop1")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NewRequired")
+ .SetDataType(TYPE_DOUBLE)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
SchemaUtil::SchemaDelta schema_delta;
schema_delta.schema_types_incompatible.emplace(kEmailType);
@@ -345,22 +382,33 @@
Eq(schema_delta));
}
-TEST_F(SchemaUtilTest, NewSchemaMissingPropertyIsIncompatible) {
+TEST(SchemaUtilTest, NewSchemaMissingPropertyIsIncompatible) {
// Configure old schema
- SchemaProto old_schema;
- auto type = old_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto property = type->add_properties();
- property->set_property_name("OldOptional");
- property->set_data_type(PropertyConfigProto::DataType::INT64);
- property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
+ SchemaProto old_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("prop1")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("OldOptional")
+ .SetDataType(TYPE_INT)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
// Configure new schema, new schema needs to at least have all the
// previously defined properties
- SchemaProto new_schema;
- type = new_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
+ SchemaProto new_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("prop1")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
SchemaUtil::SchemaDelta schema_delta;
schema_delta.schema_types_incompatible.emplace(kEmailType);
@@ -368,28 +416,30 @@
Eq(schema_delta));
}
-TEST_F(SchemaUtilTest, CompatibilityOfDifferentCardinalityOk) {
+TEST(SchemaUtilTest, CompatibilityOfDifferentCardinalityOk) {
// Configure less restrictive schema based on cardinality
- SchemaProto less_restrictive_schema;
- auto type = less_restrictive_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto property = type->add_properties();
- property->set_property_name("Property");
- property->set_data_type(PropertyConfigProto::DataType::INT64);
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
+ SchemaProto less_restrictive_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataType(TYPE_INT)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
// Configure more restrictive schema based on cardinality
- SchemaProto more_restrictive_schema;
- type = more_restrictive_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
+ SchemaProto more_restrictive_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataType(TYPE_INT)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
- property = type->add_properties();
- property->set_property_name("Property");
- property->set_data_type(PropertyConfigProto::DataType::INT64);
- property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
-
- // We can't have a new schema be less restrictive, REQUIRED->OPTIONAL
+ // We can't have a new schema be more restrictive, REPEATED->OPTIONAL
SchemaUtil::SchemaDelta incompatible_schema_delta;
incompatible_schema_delta.schema_types_incompatible.emplace(kEmailType);
EXPECT_THAT(SchemaUtil::ComputeCompatibilityDelta(
@@ -397,7 +447,7 @@
/*new_schema=*/more_restrictive_schema),
Eq(incompatible_schema_delta));
- // We can have the new schema be more restrictive, OPTIONAL->REPEATED;
+ // We can have the new schema be less restrictive, OPTIONAL->REPEATED;
SchemaUtil::SchemaDelta compatible_schema_delta;
EXPECT_THAT(SchemaUtil::ComputeCompatibilityDelta(
/*old_schema=*/more_restrictive_schema,
@@ -405,26 +455,28 @@
Eq(compatible_schema_delta));
}
-TEST_F(SchemaUtilTest, DifferentDataTypeIsIncompatible) {
+TEST(SchemaUtilTest, DifferentDataTypeIsIncompatible) {
// Configure old schema, with an int64_t property
- SchemaProto old_schema;
- auto type = old_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- auto property = type->add_properties();
- property->set_property_name("Property");
- property->set_data_type(PropertyConfigProto::DataType::INT64);
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
+ SchemaProto old_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataType(TYPE_INT)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
// Configure new schema, with a double property
- SchemaProto new_schema;
- type = new_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
-
- property = type->add_properties();
- property->set_property_name("Property");
- property->set_data_type(PropertyConfigProto::DataType::DOUBLE);
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
+ SchemaProto new_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataType(TYPE_DOUBLE)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
SchemaUtil::SchemaDelta schema_delta;
schema_delta.schema_types_incompatible.emplace(kEmailType);
@@ -432,30 +484,44 @@
Eq(schema_delta));
}
-TEST_F(SchemaUtilTest, DifferentSchemaTypeIsIncompatible) {
+TEST(SchemaUtilTest, DifferentSchemaTypeIsIncompatible) {
// Configure old schema, where Property is supposed to be a Person type
- SchemaProto old_schema;
- auto type = old_schema.add_types();
- *type = CreateSchemaTypeConfig(kPersonType);
-
- *type = CreateSchemaTypeConfig(kEmailType);
- auto property = type->add_properties();
- property->set_property_name("Property");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
- property->set_schema_type(kPersonType);
+ SchemaProto old_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kPersonType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("prop")
+ .SetDataType(TYPE_INT)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeDocument(
+ kPersonType,
+ /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
// Configure new schema, where Property is supposed to be an Email type
- SchemaProto new_schema;
- type = new_schema.add_types();
- *type = CreateSchemaTypeConfig(kPersonType);
-
- *type = CreateSchemaTypeConfig(kEmailType);
- property = type->add_properties();
- property->set_property_name("Property");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
- property->set_schema_type(kEmailType);
+ SchemaProto new_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kPersonType)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("prop")
+ .SetDataType(TYPE_INT)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeDocument(
+ kEmailType, /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
SchemaUtil::SchemaDelta schema_delta;
schema_delta.schema_types_incompatible.emplace(kEmailType);
@@ -463,74 +529,74 @@
Eq(schema_delta));
}
-TEST_F(SchemaUtilTest, ChangingIndexedPropertiesMakesIndexIncompatible) {
+TEST(SchemaUtilTest, ChangingIndexedPropertiesMakesIndexIncompatible) {
// Configure old schema
- SchemaProto old_schema;
- auto old_type = old_schema.add_types();
- *old_type = CreateSchemaTypeConfig(kEmailType, kPersonType);
-
- auto old_property = old_type->add_properties();
- old_property->set_property_name("Property");
- old_property->set_data_type(PropertyConfigProto::DataType::STRING);
- old_property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
+ SchemaProto schema_with_indexed_property =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kPersonType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
// Configure new schema
- SchemaProto new_schema;
- auto new_type = new_schema.add_types();
- *new_type = CreateSchemaTypeConfig(kEmailType, kPersonType);
-
- auto new_property = new_type->add_properties();
- new_property->set_property_name("Property");
- new_property->set_data_type(PropertyConfigProto::DataType::STRING);
- new_property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
+ SchemaProto schema_with_unindexed_property =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kPersonType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeString(MATCH_UNKNOWN, TOKENIZER_NONE)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
SchemaUtil::SchemaDelta schema_delta;
schema_delta.index_incompatible = true;
// New schema gained a new indexed property.
- old_property->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::UNKNOWN);
- new_property->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::EXACT_ONLY);
- EXPECT_THAT(SchemaUtil::ComputeCompatibilityDelta(old_schema, new_schema),
+ EXPECT_THAT(SchemaUtil::ComputeCompatibilityDelta(
+ schema_with_indexed_property, schema_with_unindexed_property),
Eq(schema_delta));
// New schema lost an indexed property.
- old_property->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::EXACT_ONLY);
- new_property->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::UNKNOWN);
- EXPECT_THAT(SchemaUtil::ComputeCompatibilityDelta(old_schema, new_schema),
+ EXPECT_THAT(SchemaUtil::ComputeCompatibilityDelta(
+ schema_with_indexed_property, schema_with_unindexed_property),
Eq(schema_delta));
}
-TEST_F(SchemaUtilTest, AddingNewIndexedPropertyMakesIndexIncompatible) {
+TEST(SchemaUtilTest, AddingNewIndexedPropertyMakesIndexIncompatible) {
// Configure old schema
- SchemaProto old_schema;
- auto old_type = old_schema.add_types();
- *old_type = CreateSchemaTypeConfig(kEmailType, kPersonType);
-
- auto old_property = old_type->add_properties();
- old_property->set_property_name("Property");
- old_property->set_data_type(PropertyConfigProto::DataType::STRING);
- old_property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
+ SchemaProto old_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kPersonType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
// Configure new schema
- SchemaProto new_schema;
- auto new_type = new_schema.add_types();
- *new_type = CreateSchemaTypeConfig(kEmailType, kPersonType);
-
- auto new_property = new_type->add_properties();
- new_property->set_property_name("Property");
- new_property->set_data_type(PropertyConfigProto::DataType::STRING);
- new_property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
-
- new_property = new_type->add_properties();
- new_property->set_property_name("NewIndexedProperty");
- new_property->set_data_type(PropertyConfigProto::DataType::STRING);
- new_property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
- new_property->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::EXACT_ONLY);
+ SchemaProto new_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kPersonType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL))
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("NewIndexedProperty")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
SchemaUtil::SchemaDelta schema_delta;
schema_delta.index_incompatible = true;
@@ -538,37 +604,75 @@
Eq(schema_delta));
}
-TEST_F(SchemaUtilTest, AddingTypeIsCompatible) {
+TEST(SchemaUtilTest, AddingTypeIsCompatible) {
// Can add a new type, existing data isn't incompatible, since none of them
// are of this new schema type
- SchemaProto old_schema;
- auto type = old_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
+ SchemaProto old_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kPersonType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
- SchemaProto new_schema;
- type = new_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
- type = new_schema.add_types();
- *type = CreateSchemaTypeConfig(kPersonType);
+ SchemaProto new_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kPersonType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
SchemaUtil::SchemaDelta schema_delta;
EXPECT_THAT(SchemaUtil::ComputeCompatibilityDelta(old_schema, new_schema),
Eq(schema_delta));
}
-TEST_F(SchemaUtilTest, DeletingTypeIsNoted) {
+TEST(SchemaUtilTest, DeletingTypeIsNoted) {
// Can't remove an old type, new schema needs to at least have all the
// previously defined schema otherwise the Documents of the missing schema
// are invalid
- SchemaProto old_schema;
- auto type = old_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
- type = old_schema.add_types();
- *type = CreateSchemaTypeConfig(kPersonType);
+ SchemaProto old_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kPersonType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
- SchemaProto new_schema;
- type = new_schema.add_types();
- *type = CreateSchemaTypeConfig(kEmailType);
+ SchemaProto new_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kEmailType)
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Property")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
SchemaUtil::SchemaDelta schema_delta;
schema_delta.schema_types_deleted.emplace(kPersonType);
@@ -576,148 +680,147 @@
Eq(schema_delta));
}
-TEST_F(SchemaUtilTest, ValidateStringIndexingConfigShouldHaveTermMatchType) {
- SchemaProto schema;
- auto* type = schema.add_types();
- type->set_schema_type("MyType");
-
- auto* prop = type->add_properties();
- prop->set_property_name("Foo");
- prop->set_data_type(PropertyConfigProto::DataType::STRING);
- prop->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
- prop->mutable_string_indexing_config()->set_tokenizer_type(
- StringIndexingConfig::TokenizerType::PLAIN);
+TEST(SchemaUtilTest, ValidateStringIndexingConfigShouldHaveTermMatchType) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("MyType").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Foo")
+ .SetDataTypeString(MATCH_UNKNOWN, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
// Error if we don't set a term match type
EXPECT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
// Passes once we set a term match type
- prop->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::EXACT_ONLY);
+ schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("MyType").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Foo")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
EXPECT_THAT(SchemaUtil::Validate(schema), IsOk());
}
-TEST_F(SchemaUtilTest, ValidateStringIndexingConfigShouldHaveTokenizer) {
- SchemaProto schema;
- auto* type = schema.add_types();
- type->set_schema_type("MyType");
-
- auto* prop = type->add_properties();
- prop->set_property_name("Foo");
- prop->set_data_type(PropertyConfigProto::DataType::STRING);
- prop->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
- prop->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::EXACT_ONLY);
+TEST(SchemaUtilTest, ValidateStringIndexingConfigShouldHaveTokenizer) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("MyType").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Foo")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_NONE)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
// Error if we don't set a tokenizer type
EXPECT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
// Passes once we set a tokenizer type
- prop->mutable_string_indexing_config()->set_tokenizer_type(
- StringIndexingConfig::TokenizerType::PLAIN);
+ schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("MyType").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("Foo")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_REQUIRED)))
+ .Build();
EXPECT_THAT(SchemaUtil::Validate(schema), IsOk());
}
-TEST_F(SchemaUtilTest, MultipleReferencesToSameNestedSchemaOk) {
- SchemaProto schema;
-
- // Create a parent schema
- auto type = schema.add_types();
- type->set_schema_type("ParentSchema");
-
- // Create multiple references to the same child schema
- auto property = type->add_properties();
- property->set_property_name("ChildProperty1");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_schema_type("ChildSchema");
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
-
- property = type->add_properties();
- property->set_property_name("ChildProperty2");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_schema_type("ChildSchema");
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
-
- // Create a child schema
- type = schema.add_types();
- type->set_schema_type("ChildSchema");
+TEST(SchemaUtilTest, MultipleReferencesToSameNestedSchemaOk) {
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("ChildSchema"))
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType("ParentSchema")
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("ChildProperty1")
+ .SetDataTypeDocument(
+ "ChildSchema",
+ /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REPEATED))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("ChildProperty2")
+ .SetDataTypeDocument(
+ "ChildSchema",
+ /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
EXPECT_THAT(SchemaUtil::Validate(schema), IsOk());
}
-TEST_F(SchemaUtilTest, InvalidSelfReference) {
- SchemaProto schema;
-
+TEST(SchemaUtilTest, InvalidSelfReference) {
// Create a schema with a self-reference cycle in it: OwnSchema -> OwnSchema
- auto type = schema.add_types();
- type->set_schema_type("OwnSchema");
-
- // Reference a child schema, so far so good
- auto property = type->add_properties();
- property->set_property_name("NestedDocument");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_schema_type("OwnSchema");
- property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType("OwnSchema")
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NestedDocument")
+ .SetDataTypeDocument(
+ "OwnSchema",
+ /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
EXPECT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT,
HasSubstr("Infinite loop")));
}
-TEST_F(SchemaUtilTest, InvalidSelfReferenceEvenWithOtherProperties) {
- SchemaProto schema;
-
+TEST(SchemaUtilTest, InvalidSelfReferenceEvenWithOtherProperties) {
// Create a schema with a self-reference cycle in it: OwnSchema -> OwnSchema
- auto type = schema.add_types();
- type->set_schema_type("OwnSchema");
-
- // Reference a child schema, so far so good
- auto property = type->add_properties();
- property->set_property_name("NestedDocument");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_schema_type("OwnSchema");
- property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
-
- property = type->add_properties();
- property->set_property_name("SomeString");
- property->set_data_type(PropertyConfigProto::DataType::STRING);
- property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
- property->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::PREFIX);
- property->mutable_string_indexing_config()->set_tokenizer_type(
- StringIndexingConfig::TokenizerType::PLAIN);
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType("OwnSchema")
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NestedDocument")
+ .SetDataTypeDocument(
+ "OwnSchema",
+ /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_OPTIONAL))
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("SomeString")
+ .SetDataTypeString(MATCH_PREFIX, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
EXPECT_THAT(SchemaUtil::Validate(schema),
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT,
HasSubstr("Infinite loop")));
}
-TEST_F(SchemaUtilTest, InvalidInfiniteLoopTwoDegrees) {
- SchemaProto schema;
-
+TEST(SchemaUtilTest, InvalidInfiniteLoopTwoDegrees) {
// Create a schema for the parent schema
- auto type = schema.add_types();
- type->set_schema_type("A");
-
- // Reference schema B, so far so good
- auto property = type->add_properties();
- property->set_property_name("NestedDocument");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_schema_type("B");
- property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
-
- // Create the child schema
- type = schema.add_types();
- type->set_schema_type("B");
-
- // Reference the schema A, causing an infinite loop of references.
- property = type->add_properties();
- property->set_property_name("NestedDocument");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_schema_type("A");
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(
+ SchemaTypeConfigBuilder()
+ .SetType("A")
+ // Reference schema B, so far so good
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NestedDocument")
+ .SetDataTypeDocument(
+ "B", /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ // Create the child schema
+ .AddType(
+ SchemaTypeConfigBuilder()
+ .SetType("B")
+ // Reference the schema A, causing an infinite loop of
+ // references.
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NestedDocument")
+ .SetDataTypeDocument(
+ "A", /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
// Two degrees of referencing: A -> B -> A
EXPECT_THAT(SchemaUtil::Validate(schema),
@@ -725,41 +828,40 @@
HasSubstr("Infinite loop")));
}
-TEST_F(SchemaUtilTest, InvalidInfiniteLoopThreeDegrees) {
- SchemaProto schema;
-
- // Create a schema for the parent schema
- auto type = schema.add_types();
- type->set_schema_type("A");
-
- // Reference schema B , so far so good
- auto property = type->add_properties();
- property->set_property_name("NestedDocument");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_schema_type("B");
- property->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
-
- // Create the child schema
- type = schema.add_types();
- type->set_schema_type("B");
-
- // Reference schema C, so far so good
- property = type->add_properties();
- property->set_property_name("NestedDocument");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_schema_type("C");
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
-
- // Create the child schema
- type = schema.add_types();
- type->set_schema_type("C");
-
- // Reference schema A, no good
- property = type->add_properties();
- property->set_property_name("NestedDocument");
- property->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- property->set_schema_type("A");
- property->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
+TEST(SchemaUtilTest, InvalidInfiniteLoopThreeDegrees) {
+ SchemaProto schema =
+ SchemaBuilder()
+ // Create a schema for the parent schema
+ .AddType(
+ SchemaTypeConfigBuilder()
+ .SetType("A")
+ // Reference schema B, so far so good
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NestedDocument")
+ .SetDataTypeDocument(
+ "B", /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ // Create the child schema
+ .AddType(
+ SchemaTypeConfigBuilder()
+ .SetType("B")
+ // Reference schema C, so far so good
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NestedDocument")
+ .SetDataTypeDocument(
+ "C", /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ // Create the child schema
+ .AddType(
+ SchemaTypeConfigBuilder()
+ .SetType("C")
+ // Reference schema C, so far so good
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("NestedDocument")
+ .SetDataTypeDocument(
+ "A", /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
// Three degrees of referencing: A -> B -> C -> A
EXPECT_THAT(SchemaUtil::Validate(schema),
diff --git a/icing/scoring/bm25f-calculator.cc b/icing/scoring/bm25f-calculator.cc
index 7495e98..4822d7f 100644
--- a/icing/scoring/bm25f-calculator.cc
+++ b/icing/scoring/bm25f-calculator.cc
@@ -42,24 +42,25 @@
constexpr float b_ = 0.7f;
// TODO(b/158603900): add tests for Bm25fCalculator
-Bm25fCalculator::Bm25fCalculator(const DocumentStore *document_store)
+Bm25fCalculator::Bm25fCalculator(const DocumentStore* document_store)
: document_store_(document_store) {}
// During initialization, Bm25fCalculator iterates through
// hit-iterators for each query term to pre-compute n(q_i) for each corpus under
// consideration.
void Bm25fCalculator::PrepareToScore(
- std::unordered_map<std::string, std::unique_ptr<DocHitInfoIterator>>
- *query_term_iterators) {
+ std::unordered_map<std::string, std::unique_ptr<DocHitInfoIterator>>*
+ query_term_iterators) {
Clear();
TermId term_id = 0;
- for (auto &iter : *query_term_iterators) {
- const std::string &term = iter.first;
+ for (auto& iter : *query_term_iterators) {
+ const std::string& term = iter.first;
if (term_id_map_.find(term) != term_id_map_.end()) {
continue;
}
term_id_map_[term] = ++term_id;
- DocHitInfoIterator *term_it = iter.second.get();
+ DocHitInfoIterator* term_it = iter.second.get();
+
while (term_it->Advance().ok()) {
auto status_or = document_store_->GetDocumentAssociatedScoreData(
term_it->doc_hit_info().document_id());
@@ -89,8 +90,8 @@
// where IDF(q_i) is the Inverse Document Frequency (IDF) weight of the query
// term q_i in the corpus with document D, and tf(q_i, D) is the weighted and
// normalized term frequency of query term q_i in the document D.
-float Bm25fCalculator::ComputeScore(const DocHitInfoIterator *query_it,
- const DocHitInfo &hit_info,
+float Bm25fCalculator::ComputeScore(const DocHitInfoIterator* query_it,
+ const DocHitInfo& hit_info,
double default_score) {
auto status_or =
document_store_->GetDocumentAssociatedScoreData(hit_info.document_id());
@@ -103,7 +104,7 @@
query_it->PopulateMatchedTermsStats(&matched_terms_stats);
float score = 0;
- for (const TermMatchInfo &term_match_info : matched_terms_stats) {
+ for (const TermMatchInfo& term_match_info : matched_terms_stats) {
float idf_weight =
GetCorpusIdfWeightForTerm(term_match_info.term, data.corpus_id());
float normalized_tf =
@@ -186,8 +187,8 @@
// |D| is the #tokens in D, avgdl is the average document length in the corpus,
// k1 and b are smoothing parameters.
float Bm25fCalculator::ComputedNormalizedTermFrequency(
- const TermMatchInfo &term_match_info, const DocHitInfo &hit_info,
- const DocumentAssociatedScoreData &data) {
+ const TermMatchInfo& term_match_info, const DocHitInfo& hit_info,
+ const DocumentAssociatedScoreData& data) {
uint32_t dl = data.length_in_tokens();
float avgdl = GetCorpusAvgDocLength(data.corpus_id());
float f_q =
@@ -204,7 +205,7 @@
// Note: once we support section weights, we should update this function to
// compute the weighted term frequency.
float Bm25fCalculator::ComputeTermFrequencyForMatchedSections(
- CorpusId corpus_id, const TermMatchInfo &term_match_info) const {
+ CorpusId corpus_id, const TermMatchInfo& term_match_info) const {
float sum = 0.0f;
SectionIdMask sections = term_match_info.section_ids_mask;
while (sections != 0) {
diff --git a/icing/store/document-store.cc b/icing/store/document-store.cc
index 33c0d1a..ac2dc9a 100644
--- a/icing/store/document-store.cc
+++ b/icing/store/document-store.cc
@@ -950,7 +950,7 @@
// existing Status.
auto document_id_or = GetDocumentId(name_space, uri);
if (absl_ports::IsNotFound(document_id_or.status())) {
- ICING_LOG(ERROR) << document_id_or.status().error_message();
+ ICING_VLOG(1) << document_id_or.status().error_message();
return libtextclassifier3::Status(
document_id_or.status().CanonicalCode(),
IcingStringUtil::StringPrintf("Document (%s, %s) not found.",
diff --git a/icing/store/document-store_test.cc b/icing/store/document-store_test.cc
index 02e5f1b..7b04a76 100644
--- a/icing/store/document-store_test.cc
+++ b/icing/store/document-store_test.cc
@@ -32,6 +32,7 @@
#include "icing/proto/document.pb.h"
#include "icing/proto/schema.pb.h"
#include "icing/proto/storage.pb.h"
+#include "icing/schema-builder.h"
#include "icing/schema/schema-store.h"
#include "icing/store/corpus-associated-scoring-data.h"
#include "icing/store/corpus-id.h"
@@ -81,6 +82,14 @@
return std::move(NamespaceStorageInfoProto());
}
+constexpr PropertyConfigProto_Cardinality_Code CARDINALITY_OPTIONAL =
+ PropertyConfigProto_Cardinality_Code_OPTIONAL;
+
+constexpr StringIndexingConfig_TokenizerType_Code TOKENIZER_PLAIN =
+ StringIndexingConfig_TokenizerType_Code_PLAIN;
+
+constexpr TermMatchType_Code MATCH_EXACT = TermMatchType_Code_EXACT_ONLY;
+
UsageReport CreateUsageReport(std::string name_space, std::string uri,
int64 timestamp_ms,
UsageReport::UsageType usage_type) {
@@ -141,28 +150,22 @@
filesystem_.CreateDirectoryRecursively(document_store_dir_.c_str());
filesystem_.CreateDirectoryRecursively(schema_store_dir_.c_str());
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
-
- auto subject = type_config->add_properties();
- subject->set_property_name("subject");
- subject->set_data_type(PropertyConfigProto::DataType::STRING);
- subject->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
- subject->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::EXACT_ONLY);
- subject->mutable_string_indexing_config()->set_tokenizer_type(
- StringIndexingConfig::TokenizerType::PLAIN);
-
- auto body = type_config->add_properties();
- body->set_property_name("body");
- body->set_data_type(PropertyConfigProto::DataType::STRING);
- body->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
- body->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::EXACT_ONLY);
- body->mutable_string_indexing_config()->set_tokenizer_type(
- StringIndexingConfig::TokenizerType::PLAIN);
-
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(
+ SchemaTypeConfigBuilder()
+ .SetType("email")
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("subject")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL))
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("body")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
SchemaStore::Create(&filesystem_, schema_store_dir_, &fake_clock_));
@@ -742,14 +745,12 @@
}
TEST_F(DocumentStoreTest, SoftDeleteBySchemaTypeOk) {
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
- type_config = schema.add_types();
- type_config->set_schema_type("message");
- type_config = schema.add_types();
- type_config->set_schema_type("person");
-
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .AddType(SchemaTypeConfigBuilder().SetType("person"))
+ .Build();
std::string schema_store_dir = schema_store_dir_ + "_custom";
filesystem_.DeleteDirectoryRecursively(schema_store_dir.c_str());
filesystem_.CreateDirectoryRecursively(schema_store_dir.c_str());
@@ -829,13 +830,12 @@
}
TEST_F(DocumentStoreTest, HardDeleteBySchemaTypeOk) {
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
- type_config = schema.add_types();
- type_config->set_schema_type("message");
- type_config = schema.add_types();
- type_config->set_schema_type("person");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .AddType(SchemaTypeConfigBuilder().SetType("person"))
+ .Build();
std::string schema_store_dir = schema_store_dir_ + "_custom";
filesystem_.DeleteDirectoryRecursively(schema_store_dir.c_str());
@@ -1004,11 +1004,11 @@
}
TEST_F(DocumentStoreTest, DeleteBySchemaTypeRecoversOk) {
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
- type_config = schema.add_types();
- type_config->set_schema_type("message");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
std::string schema_store_dir = schema_store_dir_ + "_custom";
filesystem_.DeleteDirectoryRecursively(schema_store_dir.c_str());
@@ -1088,11 +1088,11 @@
}
TEST_F(DocumentStoreTest, DeletedSchemaTypeFromSchemaStoreRecoversOk) {
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
- type_config = schema.add_types();
- type_config->set_schema_type("message");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
std::string schema_store_dir = schema_store_dir_ + "_custom";
filesystem_.DeleteDirectoryRecursively(schema_store_dir.c_str());
@@ -1157,10 +1157,10 @@
filesystem_.DeleteFile(header_file.c_str());
filesystem_.Write(header_file.c_str(), &header, sizeof(header));
- SchemaProto new_schema;
- type_config = new_schema.add_types();
- type_config->set_schema_type("message");
-
+ SchemaProto new_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
ICING_EXPECT_OK(schema_store->SetSchema(
new_schema, /*ignore_errors_and_delete_documents=*/true));
@@ -2311,11 +2311,11 @@
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<SchemaStore> schema_store,
SchemaStore::Create(&filesystem_, schema_store_dir, &fake_clock_));
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
- type_config = schema.add_types();
- type_config->set_schema_type("message");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
ICING_EXPECT_OK(schema_store->SetSchema(schema));
ICING_ASSERT_OK_AND_ASSIGN(SchemaTypeId email_schema_type_id,
@@ -2376,9 +2376,10 @@
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<SchemaStore> schema_store,
SchemaStore::Create(&filesystem_, schema_store_dir, &fake_clock_));
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
+
+ SchemaProto schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_EXPECT_OK(schema_store->SetSchema(schema));
ICING_ASSERT_OK_AND_ASSIGN(SchemaTypeId email_schema_type_id,
@@ -2424,11 +2425,11 @@
filesystem_.CreateDirectoryRecursively(schema_store_dir.c_str());
// Set a schema
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
- type_config = schema.add_types();
- type_config->set_schema_type("message");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<SchemaStore> schema_store,
@@ -2476,11 +2477,10 @@
// Rearrange the schema types. Since SchemaTypeId is assigned based on order,
// this should change the SchemaTypeIds.
- schema.clear_types();
- type_config = schema.add_types();
- type_config->set_schema_type("message");
- type_config = schema.add_types();
- type_config->set_schema_type("email");
+ schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_EXPECT_OK(schema_store->SetSchema(schema));
@@ -2511,18 +2511,14 @@
filesystem_.CreateDirectoryRecursively(schema_store_dir.c_str());
// Set a schema
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
-
- auto property_config = type_config->add_properties();
- property_config->set_property_name("subject");
- property_config->set_data_type(PropertyConfigProto::DataType::STRING);
- property_config->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
- property_config->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::EXACT_ONLY);
- property_config->mutable_string_indexing_config()->set_tokenizer_type(
- StringIndexingConfig::TokenizerType::PLAIN);
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("subject")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<SchemaStore> schema_store,
@@ -2589,11 +2585,11 @@
filesystem_.CreateDirectoryRecursively(schema_store_dir.c_str());
// Set a schema
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
- type_config = schema.add_types();
- type_config->set_schema_type("message");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<SchemaStore> schema_store,
@@ -2633,9 +2629,10 @@
EXPECT_THAT(document_store->Get(message_document_id),
IsOkAndHolds(EqualsProto(message_document)));
- SchemaProto new_schema;
- type_config = new_schema.add_types();
- type_config->set_schema_type("message");
+ SchemaProto new_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
ICING_EXPECT_OK(
schema_store->SetSchema(new_schema,
@@ -2658,11 +2655,11 @@
filesystem_.CreateDirectoryRecursively(schema_store_dir.c_str());
// Set a schema
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
- type_config = schema.add_types();
- type_config->set_schema_type("message");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<SchemaStore> schema_store,
@@ -2710,11 +2707,10 @@
// Rearrange the schema types. Since SchemaTypeId is assigned based on order,
// this should change the SchemaTypeIds.
- schema.clear_types();
- type_config = schema.add_types();
- type_config->set_schema_type("message");
- type_config = schema.add_types();
- type_config->set_schema_type("email");
+ schema = SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(SchemaStore::SetSchemaResult set_schema_result,
schema_store->SetSchema(schema));
@@ -2747,18 +2743,14 @@
filesystem_.CreateDirectoryRecursively(schema_store_dir.c_str());
// Set a schema
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
-
- auto property_config = type_config->add_properties();
- property_config->set_property_name("subject");
- property_config->set_data_type(PropertyConfigProto::DataType::STRING);
- property_config->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
- property_config->mutable_string_indexing_config()->set_term_match_type(
- TermMatchType::EXACT_ONLY);
- property_config->mutable_string_indexing_config()->set_tokenizer_type(
- StringIndexingConfig::TokenizerType::PLAIN);
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email").AddProperty(
+ PropertyConfigBuilder()
+ .SetName("subject")
+ .SetDataTypeString(MATCH_EXACT, TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<SchemaStore> schema_store,
@@ -2828,11 +2820,11 @@
filesystem_.CreateDirectoryRecursively(schema_store_dir.c_str());
// Set a schema
- SchemaProto schema;
- auto type_config = schema.add_types();
- type_config->set_schema_type("email");
- type_config = schema.add_types();
- type_config->set_schema_type("message");
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("email"))
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<SchemaStore> schema_store,
@@ -2872,9 +2864,10 @@
EXPECT_THAT(document_store->Get(message_document_id),
IsOkAndHolds(EqualsProto(message_document)));
- SchemaProto new_schema;
- type_config = new_schema.add_types();
- type_config->set_schema_type("message");
+ SchemaProto new_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder().SetType("message"))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
SchemaStore::SetSchemaResult set_schema_result,
diff --git a/icing/util/document-validator_test.cc b/icing/util/document-validator_test.cc
index f05e8a6..cb013d7 100644
--- a/icing/util/document-validator_test.cc
+++ b/icing/util/document-validator_test.cc
@@ -21,6 +21,7 @@
#include "icing/document-builder.h"
#include "icing/file/filesystem.h"
#include "icing/proto/schema.pb.h"
+#include "icing/schema-builder.h"
#include "icing/schema/schema-store.h"
#include "icing/testing/common-matchers.h"
#include "icing/testing/fake-clock.h"
@@ -45,17 +46,52 @@
constexpr char kDefaultNamespace[] = "icing";
constexpr char kDefaultString[] = "This is a string.";
+constexpr PropertyConfigProto_Cardinality_Code CARDINALITY_OPTIONAL =
+ PropertyConfigProto_Cardinality_Code_OPTIONAL;
+constexpr PropertyConfigProto_Cardinality_Code CARDINALITY_REQUIRED =
+ PropertyConfigProto_Cardinality_Code_REQUIRED;
+constexpr PropertyConfigProto_Cardinality_Code CARDINALITY_REPEATED =
+ PropertyConfigProto_Cardinality_Code_REPEATED;
+
+constexpr PropertyConfigProto_DataType_Code TYPE_STRING =
+ PropertyConfigProto_DataType_Code_STRING;
+
class DocumentValidatorTest : public ::testing::Test {
protected:
DocumentValidatorTest() {}
void SetUp() override {
- SchemaProto schema;
- auto type_config = schema.add_types();
- CreateEmailTypeConfig(type_config);
-
- type_config = schema.add_types();
- CreateConversationTypeConfig(type_config);
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(
+ SchemaTypeConfigBuilder()
+ .SetType(kTypeEmail)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName(kPropertySubject)
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName(kPropertyText)
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_OPTIONAL))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName(kPropertyRecipients)
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .AddType(
+ SchemaTypeConfigBuilder()
+ .SetType(kTypeConversation)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName(kPropertyName)
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED))
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName(kPropertyEmails)
+ .SetDataTypeDocument(
+ kTypeEmail, /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
ICING_ASSERT_OK_AND_ASSIGN(
schema_store_,
@@ -66,25 +102,6 @@
std::make_unique<DocumentValidator>(schema_store_.get());
}
- static void CreateEmailTypeConfig(SchemaTypeConfigProto* type_config) {
- type_config->set_schema_type(kTypeEmail);
-
- auto subject = type_config->add_properties();
- subject->set_property_name(kPropertySubject);
- subject->set_data_type(PropertyConfigProto::DataType::STRING);
- subject->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
-
- auto text = type_config->add_properties();
- text->set_property_name(kPropertyText);
- text->set_data_type(PropertyConfigProto::DataType::STRING);
- text->set_cardinality(PropertyConfigProto::Cardinality::OPTIONAL);
-
- auto recipients = type_config->add_properties();
- recipients->set_property_name(kPropertyRecipients);
- recipients->set_data_type(PropertyConfigProto::DataType::STRING);
- recipients->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
- }
-
static DocumentBuilder SimpleEmailBuilder() {
return DocumentBuilder()
.SetKey(kDefaultNamespace, "email/1")
@@ -95,21 +112,6 @@
kDefaultString);
}
- static void CreateConversationTypeConfig(SchemaTypeConfigProto* type_config) {
- type_config->set_schema_type(kTypeConversation);
-
- auto name = type_config->add_properties();
- name->set_property_name(kPropertyName);
- name->set_data_type(PropertyConfigProto::DataType::STRING);
- name->set_cardinality(PropertyConfigProto::Cardinality::REQUIRED);
-
- auto emails = type_config->add_properties();
- emails->set_property_name(kPropertyEmails);
- emails->set_data_type(PropertyConfigProto::DataType::DOCUMENT);
- emails->set_cardinality(PropertyConfigProto::Cardinality::REPEATED);
- emails->set_schema_type(kTypeEmail);
- }
-
static DocumentBuilder SimpleConversationBuilder() {
return DocumentBuilder()
.SetKey(kDefaultNamespace, "conversation/1")
@@ -326,12 +328,26 @@
}
TEST_F(DocumentValidatorTest, HandleTypeConfigMapChangesOk) {
- SchemaProto email_schema;
- auto type_config = email_schema.add_types();
- CreateEmailTypeConfig(type_config);
+ SchemaProto email_schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kTypeEmail)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName(kPropertySubject)
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName(kPropertyText)
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_OPTIONAL))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName(kPropertyRecipients)
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
- // Create a custom directory so we don't collide with the test's preset schema
- // in SetUp
+ // Create a custom directory so we don't collide
+ // with the test's preset schema in SetUp
const std::string custom_schema_dir = GetTestTempDir() + "/custom_schema";
filesystem_.DeleteDirectoryRecursively(custom_schema_dir.c_str());
filesystem_.CreateDirectoryRecursively(custom_schema_dir.c_str());
@@ -352,9 +368,21 @@
HasSubstr("'Conversation' not found")));
// Add the 'Conversation' type
- SchemaProto email_and_conversation_schema = email_schema;
- type_config = email_and_conversation_schema.add_types();
- CreateConversationTypeConfig(type_config);
+ SchemaProto email_and_conversation_schema =
+ SchemaBuilder(email_schema)
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType(kTypeConversation)
+ .AddProperty(PropertyConfigBuilder()
+ .SetName(kPropertyName)
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_REQUIRED))
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName(kPropertyEmails)
+ .SetDataTypeDocument(
+ kTypeEmail, /*index_nested_properties=*/true)
+ .SetCardinality(CARDINALITY_REPEATED)))
+ .Build();
// DocumentValidator should be able to handle the SchemaStore getting updated
// separately
diff --git a/proto/icing/proto/logging.proto b/proto/icing/proto/logging.proto
index e9509d4..a9780b5 100644
--- a/proto/icing/proto/logging.proto
+++ b/proto/icing/proto/logging.proto
@@ -125,7 +125,7 @@
// Stats of the top-level function IcingSearchEngine::Search() and
// IcingSearchEngine::GetNextPage().
-// Next tag: 15
+// Next tag: 16
message QueryStatsProto {
// Number of terms in the query string.
optional int32 num_terms = 1;
@@ -154,7 +154,7 @@
optional int32 num_documents_scored = 8;
// How many of the results in the page returned were snippeted.
- optional bool num_results_snippeted = 9;
+ optional int32 num_results_with_snippets = 15;
// Overall time used for the function call.
optional int32 latency_ms = 10;
@@ -172,6 +172,8 @@
// Time used to fetch the document protos. Note that it includes the
// time to snippet if ‘has_snippets’ is true.
optional int32 document_retrieval_latency_ms = 14;
+
+ reserved 9;
}
// Stats of the top-level functions IcingSearchEngine::Delete,
diff --git a/synced_AOSP_CL_number.txt b/synced_AOSP_CL_number.txt
index 7fc9855..56fb657 100644
--- a/synced_AOSP_CL_number.txt
+++ b/synced_AOSP_CL_number.txt
@@ -1 +1 @@
-set(synced_AOSP_CL_number=362581751)
+set(synced_AOSP_CL_number=366069684)