From fdc4c4ee78731add1a8f4dd4bb7623fcce9b32cd Mon Sep 17 00:00:00 2001 From: Morgan Chen Date: Tue, 11 Nov 2025 09:04:14 -0800 Subject: [PATCH 01/36] fix lint errors --- Firestore/core/src/api/expressions.h | 2 +- Firestore/core/src/api/pipeline_result.h | 2 +- Firestore/core/src/api/query_snapshot.cc | 1 + Firestore/core/src/api/query_snapshot.h | 1 + Firestore/core/src/api/realtime_pipeline_snapshot.h | 2 +- Firestore/core/src/core/view.cc | 2 +- 6 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Firestore/core/src/api/expressions.h b/Firestore/core/src/api/expressions.h index 3cd5d5cfc68..c90dcce2eb7 100644 --- a/Firestore/core/src/api/expressions.h +++ b/Firestore/core/src/api/expressions.h @@ -43,7 +43,7 @@ class Expr { class Selectable : public Expr { public: - virtual ~Selectable() override = default; + ~Selectable() override = default; virtual const std::string& alias() const = 0; }; diff --git a/Firestore/core/src/api/pipeline_result.h b/Firestore/core/src/api/pipeline_result.h index c8db550178a..093500dcd1e 100644 --- a/Firestore/core/src/api/pipeline_result.h +++ b/Firestore/core/src/api/pipeline_result.h @@ -51,7 +51,7 @@ class PipelineResult { PipelineResult() = default; - PipelineResult(model::Document document) + explicit PipelineResult(model::Document document) : internal_key_{document->key()}, value_{document->shared_data()}, // TODO(pipeline): add create time support diff --git a/Firestore/core/src/api/query_snapshot.cc b/Firestore/core/src/api/query_snapshot.cc index 4e94d6f11e3..e2a10034a27 100644 --- a/Firestore/core/src/api/query_snapshot.cc +++ b/Firestore/core/src/api/query_snapshot.cc @@ -17,6 +17,7 @@ #include "Firestore/core/src/api/query_snapshot.h" #include +#include #include "Firestore/core/src/api/document_change.h" #include "Firestore/core/src/api/document_snapshot.h" diff --git a/Firestore/core/src/api/query_snapshot.h b/Firestore/core/src/api/query_snapshot.h index 58d7c65bf03..5a48ab37793 100644 --- a/Firestore/core/src/api/query_snapshot.h +++ b/Firestore/core/src/api/query_snapshot.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "Firestore/core/src/api/api_fwd.h" #include "Firestore/core/src/api/document_change.h" diff --git a/Firestore/core/src/api/realtime_pipeline_snapshot.h b/Firestore/core/src/api/realtime_pipeline_snapshot.h index 0b326376287..6a2fd958f32 100644 --- a/Firestore/core/src/api/realtime_pipeline_snapshot.h +++ b/Firestore/core/src/api/realtime_pipeline_snapshot.h @@ -68,4 +68,4 @@ class RealtimePipelineSnapshot { } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_API_REAL_TIME_PIPELINE_SNAPSHOT_H_ +#endif // FIRESTORE_CORE_SRC_API_REALTIME_PIPELINE_SNAPSHOT_H_ diff --git a/Firestore/core/src/core/view.cc b/Firestore/core/src/core/view.cc index 6bd612491d6..e1ccb6b838b 100644 --- a/Firestore/core/src/core/view.cc +++ b/Firestore/core/src/core/view.cc @@ -20,10 +20,10 @@ #include #include +#include "Firestore/core/src/core/pipeline_run.h" #include "Firestore/core/src/core/target.h" #include "Firestore/core/src/model/document_set.h" #include "Firestore/core/src/util/hard_assert.h" // For HARD_ASSERT and HARD_FAIL -#include "pipeline_run.h" namespace firebase { namespace firestore { From 0b3d4d1e70c1feea1c828ae79dacc2b3c20e027d Mon Sep 17 00:00:00 2001 From: Morgan Chen Date: Tue, 11 Nov 2025 09:15:58 -0800 Subject: [PATCH 02/36] fix missing header --- .../FirebaseFirestore/FIRPipelineBridge.h | 315 ++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 FirebaseFirestoreInternal/FirebaseFirestore/FIRPipelineBridge.h diff --git a/FirebaseFirestoreInternal/FirebaseFirestore/FIRPipelineBridge.h b/FirebaseFirestoreInternal/FirebaseFirestore/FIRPipelineBridge.h new file mode 100644 index 00000000000..4c8d9a041ac --- /dev/null +++ b/FirebaseFirestoreInternal/FirebaseFirestore/FIRPipelineBridge.h @@ -0,0 +1,315 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRFirestore.h" + +#import + +#import "FIRDocumentChange.h" +#import "FIRDocumentSnapshot.h" +#import "FIRSnapshotListenOptions.h" + +@class FIRTimestamp; +@class FIRVectorValue; +@class FIRPipelineBridge; +@class FIRFieldPath; + +NS_ASSUME_NONNULL_BEGIN + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(ExprBridge) +@interface FIRExprBridge : NSObject +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(FieldBridge) +@interface FIRFieldBridge : FIRExprBridge +- (id)initWithName:(NSString *)name; +- (id)initWithPath:(FIRFieldPath *)path; +- (NSString *)field_name; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(ConstantBridge) +@interface FIRConstantBridge : FIRExprBridge +- (id)init:(id)input; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(FunctionExprBridge) +@interface FIRFunctionExprBridge : FIRExprBridge +- (id)initWithName:(NSString *)name Args:(NSArray *)args; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(AggregateFunctionBridge) +@interface FIRAggregateFunctionBridge : NSObject +- (id)initWithName:(NSString *)name Args:(NSArray *)args; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(OrderingBridge) +@interface FIROrderingBridge : NSObject +- (id)initWithExpr:(FIRExprBridge *)expr Direction:(NSString *)direction; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(StageBridge) +@interface FIRStageBridge : NSObject +@property(nonatomic, readonly) NSString *name; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(CollectionSourceStageBridge) +@interface FIRCollectionSourceStageBridge : FIRStageBridge + +- (id)initWithRef:(FIRCollectionReference *)ref firestore:(FIRFirestore *)db; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(DatabaseSourceStageBridge) +@interface FIRDatabaseSourceStageBridge : FIRStageBridge + +- (id)init; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(CollectionGroupSourceStageBridge) +@interface FIRCollectionGroupSourceStageBridge : FIRStageBridge + +- (id)initWithCollectionId:(NSString *)id; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(DocumentsSourceStageBridge) +@interface FIRDocumentsSourceStageBridge : FIRStageBridge + +- (id)initWithDocuments:(NSArray *)documents firestore:(FIRFirestore *)db; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(WhereStageBridge) +@interface FIRWhereStageBridge : FIRStageBridge + +- (id)initWithExpr:(FIRExprBridge *)expr; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(LimitStageBridge) +@interface FIRLimitStageBridge : FIRStageBridge + +- (id)initWithLimit:(NSInteger)value; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(OffsetStageBridge) +@interface FIROffsetStageBridge : FIRStageBridge + +- (id)initWithOffset:(NSInteger)value; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(AddFieldsStageBridge) +@interface FIRAddFieldsStageBridge : FIRStageBridge +- (id)initWithFields:(NSDictionary *)fields; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(RemoveFieldsStageBridge) +@interface FIRRemoveFieldsStageBridge : FIRStageBridge +- (id)initWithFields:(NSArray *)fields; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(SelectStageBridge) +@interface FIRSelectStageBridge : FIRStageBridge +- (id)initWithSelections:(NSDictionary *)selections; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(DistinctStageBridge) +@interface FIRDistinctStageBridge : FIRStageBridge +- (id)initWithGroups:(NSDictionary *)groups; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(AggregateStageBridge) +@interface FIRAggregateStageBridge : FIRStageBridge +- (id)initWithAccumulators:(NSDictionary *)accumulators + groups:(NSDictionary *)groups; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(FindNearestStageBridge) +@interface FIRFindNearestStageBridge : FIRStageBridge +- (id)initWithField:(FIRFieldBridge *)field + vectorValue:(FIRVectorValue *)vectorValue + distanceMeasure:(NSString *)distanceMeasure + limit:(NSNumber *_Nullable)limit + distanceField:(FIRExprBridge *_Nullable)distanceField; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(SortStageBridge) +@interface FIRSorStageBridge : FIRStageBridge +- (id)initWithOrderings:(NSArray *)orderings; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(ReplaceWithStageBridge) +@interface FIRReplaceWithStageBridge : FIRStageBridge +- (id)initWithExpr:(FIRExprBridge *)expr; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(SampleStageBridge) +@interface FIRSampleStageBridge : FIRStageBridge +- (id)initWithCount:(int64_t)count; +- (id)initWithPercentage:(double)percentage; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(UnionStageBridge) +@interface FIRUnionStageBridge : FIRStageBridge +- (id)initWithOther:(FIRPipelineBridge *)other; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(UnnestStageBridge) +@interface FIRUnnestStageBridge : FIRStageBridge +- (id)initWithField:(FIRExprBridge *)field + alias:(FIRExprBridge *)alias + indexField:(FIRExprBridge *_Nullable)index_field; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(RawStageBridge) +@interface FIRRawStageBridge : FIRStageBridge +- (id)initWithName:(NSString *)name + params:(NSArray *)params + options:(NSDictionary *_Nullable)options; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(__PipelineResultBridge) +@interface __FIRPipelineResultBridge : NSObject + +@property(nonatomic, strong, readonly, nullable) FIRDocumentReference *reference; + +@property(nonatomic, copy, readonly, nullable) NSString *documentID; + +@property(nonatomic, strong, readonly, nullable) FIRTimestamp *create_time; + +@property(nonatomic, strong, readonly, nullable) FIRTimestamp *update_time; + +- (NSDictionary *)data; + +- (NSDictionary *)dataWithServerTimestampBehavior: + (FIRServerTimestampBehavior)serverTimestampBehavior; + +- (nullable id)get:(id)field; + +- (nullable id)get:(id)field + serverTimestampBehavior:(FIRServerTimestampBehavior)serverTimestampBehavior; + +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(__PipelineResultChangeBridge) +@interface __FIRPipelineResultChangeBridge : NSObject + +/** The type of change that occurred (added, modified, or removed). */ +@property(nonatomic, readonly) FIRDocumentChangeType type; + +/** The document affected by this change. */ +@property(nonatomic, strong, readonly) __FIRPipelineResultBridge *result; + +@property(nonatomic, readonly) NSUInteger oldIndex; + +@property(nonatomic, readonly) NSUInteger newIndex; + +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(__PipelineSnapshotBridge) +@interface __FIRPipelineSnapshotBridge : NSObject + +@property(nonatomic, strong, readonly) NSArray<__FIRPipelineResultBridge *> *results; + +@property(nonatomic, strong, readonly) FIRTimestamp *execution_time; + +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(PipelineBridge) +@interface FIRPipelineBridge : NSObject + +/** :nodoc: */ +- (id)initWithStages:(NSArray *)stages db:(FIRFirestore *)db; + +- (void)executeWithCompletion:(void (^)(__FIRPipelineSnapshotBridge *_Nullable result, + NSError *_Nullable error))completion; + ++ (NSArray *)createStageBridgesFromQuery:(FIRQuery *)query; +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(__RealtimePipelineSnapshotBridge) +@interface __FIRRealtimePipelineSnapshotBridge : NSObject + +@property(nonatomic, strong, readonly) NSArray<__FIRPipelineResultBridge *> *results; + +@property(nonatomic, strong, readonly) NSArray<__FIRPipelineResultChangeBridge *> *changes; + +@property(nonatomic, strong, readonly) FIRSnapshotMetadata *metadata; + +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(__PipelineListenOptionsBridge) +@interface __FIRPipelineListenOptionsBridge : NSObject + +@property(nonatomic, readonly) NSString *serverTimestampBehavior; +@property(nonatomic, readonly) BOOL includeMetadata; +@property(nonatomic, readonly) FIRListenSource source; +- (instancetype)initWithServerTimestampBehavior:(NSString *)serverTimestampBehavior + includeMetadata:(BOOL)includeMetadata + source:(FIRListenSource)source NS_DESIGNATED_INITIALIZER; + +/** + * The default initializer is unavailable. Please use the designated initializer. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_SWIFT_SENDABLE +NS_SWIFT_NAME(RealtimePipelineBridge) +@interface FIRRealtimePipelineBridge : NSObject + +/** :nodoc: */ +- (id)initWithStages:(NSArray *)stages db:(FIRFirestore *)db; + +- (id) + addSnapshotListenerWithOptions:(__FIRPipelineListenOptionsBridge *)options + listener: + (void (^)(__FIRRealtimePipelineSnapshotBridge *_Nullable snapshot, + NSError *_Nullable error))listener + NS_SWIFT_NAME(addSnapshotListener(options:listener:)); + +@end + +NS_ASSUME_NONNULL_END From 55524cb2910855e5c9f3388c236ef05eed2b5d39 Mon Sep 17 00:00:00 2001 From: Morgan Chen Date: Tue, 11 Nov 2025 10:25:58 -0800 Subject: [PATCH 03/36] remove file that caused build breakages --- .../FirebaseFirestore/FIRPipelineBridge.h | 315 ------------------ 1 file changed, 315 deletions(-) delete mode 100644 FirebaseFirestoreInternal/FirebaseFirestore/FIRPipelineBridge.h diff --git a/FirebaseFirestoreInternal/FirebaseFirestore/FIRPipelineBridge.h b/FirebaseFirestoreInternal/FirebaseFirestore/FIRPipelineBridge.h deleted file mode 100644 index 4c8d9a041ac..00000000000 --- a/FirebaseFirestoreInternal/FirebaseFirestore/FIRPipelineBridge.h +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FIRFirestore.h" - -#import - -#import "FIRDocumentChange.h" -#import "FIRDocumentSnapshot.h" -#import "FIRSnapshotListenOptions.h" - -@class FIRTimestamp; -@class FIRVectorValue; -@class FIRPipelineBridge; -@class FIRFieldPath; - -NS_ASSUME_NONNULL_BEGIN - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(ExprBridge) -@interface FIRExprBridge : NSObject -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(FieldBridge) -@interface FIRFieldBridge : FIRExprBridge -- (id)initWithName:(NSString *)name; -- (id)initWithPath:(FIRFieldPath *)path; -- (NSString *)field_name; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(ConstantBridge) -@interface FIRConstantBridge : FIRExprBridge -- (id)init:(id)input; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(FunctionExprBridge) -@interface FIRFunctionExprBridge : FIRExprBridge -- (id)initWithName:(NSString *)name Args:(NSArray *)args; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(AggregateFunctionBridge) -@interface FIRAggregateFunctionBridge : NSObject -- (id)initWithName:(NSString *)name Args:(NSArray *)args; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(OrderingBridge) -@interface FIROrderingBridge : NSObject -- (id)initWithExpr:(FIRExprBridge *)expr Direction:(NSString *)direction; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(StageBridge) -@interface FIRStageBridge : NSObject -@property(nonatomic, readonly) NSString *name; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(CollectionSourceStageBridge) -@interface FIRCollectionSourceStageBridge : FIRStageBridge - -- (id)initWithRef:(FIRCollectionReference *)ref firestore:(FIRFirestore *)db; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(DatabaseSourceStageBridge) -@interface FIRDatabaseSourceStageBridge : FIRStageBridge - -- (id)init; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(CollectionGroupSourceStageBridge) -@interface FIRCollectionGroupSourceStageBridge : FIRStageBridge - -- (id)initWithCollectionId:(NSString *)id; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(DocumentsSourceStageBridge) -@interface FIRDocumentsSourceStageBridge : FIRStageBridge - -- (id)initWithDocuments:(NSArray *)documents firestore:(FIRFirestore *)db; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(WhereStageBridge) -@interface FIRWhereStageBridge : FIRStageBridge - -- (id)initWithExpr:(FIRExprBridge *)expr; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(LimitStageBridge) -@interface FIRLimitStageBridge : FIRStageBridge - -- (id)initWithLimit:(NSInteger)value; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(OffsetStageBridge) -@interface FIROffsetStageBridge : FIRStageBridge - -- (id)initWithOffset:(NSInteger)value; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(AddFieldsStageBridge) -@interface FIRAddFieldsStageBridge : FIRStageBridge -- (id)initWithFields:(NSDictionary *)fields; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(RemoveFieldsStageBridge) -@interface FIRRemoveFieldsStageBridge : FIRStageBridge -- (id)initWithFields:(NSArray *)fields; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(SelectStageBridge) -@interface FIRSelectStageBridge : FIRStageBridge -- (id)initWithSelections:(NSDictionary *)selections; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(DistinctStageBridge) -@interface FIRDistinctStageBridge : FIRStageBridge -- (id)initWithGroups:(NSDictionary *)groups; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(AggregateStageBridge) -@interface FIRAggregateStageBridge : FIRStageBridge -- (id)initWithAccumulators:(NSDictionary *)accumulators - groups:(NSDictionary *)groups; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(FindNearestStageBridge) -@interface FIRFindNearestStageBridge : FIRStageBridge -- (id)initWithField:(FIRFieldBridge *)field - vectorValue:(FIRVectorValue *)vectorValue - distanceMeasure:(NSString *)distanceMeasure - limit:(NSNumber *_Nullable)limit - distanceField:(FIRExprBridge *_Nullable)distanceField; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(SortStageBridge) -@interface FIRSorStageBridge : FIRStageBridge -- (id)initWithOrderings:(NSArray *)orderings; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(ReplaceWithStageBridge) -@interface FIRReplaceWithStageBridge : FIRStageBridge -- (id)initWithExpr:(FIRExprBridge *)expr; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(SampleStageBridge) -@interface FIRSampleStageBridge : FIRStageBridge -- (id)initWithCount:(int64_t)count; -- (id)initWithPercentage:(double)percentage; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(UnionStageBridge) -@interface FIRUnionStageBridge : FIRStageBridge -- (id)initWithOther:(FIRPipelineBridge *)other; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(UnnestStageBridge) -@interface FIRUnnestStageBridge : FIRStageBridge -- (id)initWithField:(FIRExprBridge *)field - alias:(FIRExprBridge *)alias - indexField:(FIRExprBridge *_Nullable)index_field; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(RawStageBridge) -@interface FIRRawStageBridge : FIRStageBridge -- (id)initWithName:(NSString *)name - params:(NSArray *)params - options:(NSDictionary *_Nullable)options; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(__PipelineResultBridge) -@interface __FIRPipelineResultBridge : NSObject - -@property(nonatomic, strong, readonly, nullable) FIRDocumentReference *reference; - -@property(nonatomic, copy, readonly, nullable) NSString *documentID; - -@property(nonatomic, strong, readonly, nullable) FIRTimestamp *create_time; - -@property(nonatomic, strong, readonly, nullable) FIRTimestamp *update_time; - -- (NSDictionary *)data; - -- (NSDictionary *)dataWithServerTimestampBehavior: - (FIRServerTimestampBehavior)serverTimestampBehavior; - -- (nullable id)get:(id)field; - -- (nullable id)get:(id)field - serverTimestampBehavior:(FIRServerTimestampBehavior)serverTimestampBehavior; - -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(__PipelineResultChangeBridge) -@interface __FIRPipelineResultChangeBridge : NSObject - -/** The type of change that occurred (added, modified, or removed). */ -@property(nonatomic, readonly) FIRDocumentChangeType type; - -/** The document affected by this change. */ -@property(nonatomic, strong, readonly) __FIRPipelineResultBridge *result; - -@property(nonatomic, readonly) NSUInteger oldIndex; - -@property(nonatomic, readonly) NSUInteger newIndex; - -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(__PipelineSnapshotBridge) -@interface __FIRPipelineSnapshotBridge : NSObject - -@property(nonatomic, strong, readonly) NSArray<__FIRPipelineResultBridge *> *results; - -@property(nonatomic, strong, readonly) FIRTimestamp *execution_time; - -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(PipelineBridge) -@interface FIRPipelineBridge : NSObject - -/** :nodoc: */ -- (id)initWithStages:(NSArray *)stages db:(FIRFirestore *)db; - -- (void)executeWithCompletion:(void (^)(__FIRPipelineSnapshotBridge *_Nullable result, - NSError *_Nullable error))completion; - -+ (NSArray *)createStageBridgesFromQuery:(FIRQuery *)query; -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(__RealtimePipelineSnapshotBridge) -@interface __FIRRealtimePipelineSnapshotBridge : NSObject - -@property(nonatomic, strong, readonly) NSArray<__FIRPipelineResultBridge *> *results; - -@property(nonatomic, strong, readonly) NSArray<__FIRPipelineResultChangeBridge *> *changes; - -@property(nonatomic, strong, readonly) FIRSnapshotMetadata *metadata; - -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(__PipelineListenOptionsBridge) -@interface __FIRPipelineListenOptionsBridge : NSObject - -@property(nonatomic, readonly) NSString *serverTimestampBehavior; -@property(nonatomic, readonly) BOOL includeMetadata; -@property(nonatomic, readonly) FIRListenSource source; -- (instancetype)initWithServerTimestampBehavior:(NSString *)serverTimestampBehavior - includeMetadata:(BOOL)includeMetadata - source:(FIRListenSource)source NS_DESIGNATED_INITIALIZER; - -/** - * The default initializer is unavailable. Please use the designated initializer. - */ -- (instancetype)init NS_UNAVAILABLE; - -@end - -NS_SWIFT_SENDABLE -NS_SWIFT_NAME(RealtimePipelineBridge) -@interface FIRRealtimePipelineBridge : NSObject - -/** :nodoc: */ -- (id)initWithStages:(NSArray *)stages db:(FIRFirestore *)db; - -- (id) - addSnapshotListenerWithOptions:(__FIRPipelineListenOptionsBridge *)options - listener: - (void (^)(__FIRRealtimePipelineSnapshotBridge *_Nullable snapshot, - NSError *_Nullable error))listener - NS_SWIFT_NAME(addSnapshotListener(options:listener:)); - -@end - -NS_ASSUME_NONNULL_END From a077cba0d08b407edd52fc4397f2f77779eac2fe Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Tue, 11 Nov 2025 15:49:27 -0500 Subject: [PATCH 04/36] fix c++ format error --- Firestore/core/src/api/query_snapshot.h | 1 + Firestore/core/src/core/expressions_eval.cc | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Firestore/core/src/api/query_snapshot.h b/Firestore/core/src/api/query_snapshot.h index 5a48ab37793..667d73fbd6e 100644 --- a/Firestore/core/src/api/query_snapshot.h +++ b/Firestore/core/src/api/query_snapshot.h @@ -22,6 +22,7 @@ #include #include +#include #include "Firestore/core/src/api/api_fwd.h" #include "Firestore/core/src/api/document_change.h" #include "Firestore/core/src/api/document_snapshot.h" diff --git a/Firestore/core/src/core/expressions_eval.cc b/Firestore/core/src/core/expressions_eval.cc index 4ae269cec62..e313649f388 100644 --- a/Firestore/core/src/core/expressions_eval.cc +++ b/Firestore/core/src/core/expressions_eval.cc @@ -584,8 +584,8 @@ template bool ProcessUtf8(const std::string& s, T* result, std::function func) { - int i = 0; - const int len = s.size(); + size_t i = 0; + const size_t len = s.size(); const unsigned char* data = reinterpret_cast(s.data()); while (i < len) { From 8e23996af3f5027b74e705a74dacbc11d9ee31cb Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 12 Nov 2025 09:52:13 -0500 Subject: [PATCH 05/36] remove duplicate vector --- Firestore/core/src/api/query_snapshot.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Firestore/core/src/api/query_snapshot.h b/Firestore/core/src/api/query_snapshot.h index 667d73fbd6e..5a48ab37793 100644 --- a/Firestore/core/src/api/query_snapshot.h +++ b/Firestore/core/src/api/query_snapshot.h @@ -22,7 +22,6 @@ #include #include -#include #include "Firestore/core/src/api/api_fwd.h" #include "Firestore/core/src/api/document_change.h" #include "Firestore/core/src/api/document_snapshot.h" From c10da979f25946d0341d8e0cc6ed76c2b27df1a2 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 12 Nov 2025 11:53:34 -0500 Subject: [PATCH 06/36] fix c++ type error --- Firestore/core/src/core/expressions_eval.cc | 2 ++ .../test/unit/testutil/expression_test_util.h | 24 ++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Firestore/core/src/core/expressions_eval.cc b/Firestore/core/src/core/expressions_eval.cc index e313649f388..8c2cd3b12ee 100644 --- a/Firestore/core/src/core/expressions_eval.cc +++ b/Firestore/core/src/core/expressions_eval.cc @@ -447,6 +447,7 @@ EvaluateResult CoreEq::CompareToResult(const EvaluateResult& left, case model::StrictEqualsResult::kNull: return EvaluateResult::NewNull(); } + HARD_FAIL("Unhandled case in switch statement"); } EvaluateResult CoreNeq::CompareToResult(const EvaluateResult& left, @@ -469,6 +470,7 @@ EvaluateResult CoreNeq::CompareToResult(const EvaluateResult& left, case model::StrictEqualsResult::kNull: return EvaluateResult::NewNull(); } + HARD_FAIL("Unhandled case in switch statement"); } EvaluateResult CoreLt::CompareToResult(const EvaluateResult& left, diff --git a/Firestore/core/test/unit/testutil/expression_test_util.h b/Firestore/core/test/unit/testutil/expression_test_util.h index fab0296b44a..3386c03d2fb 100644 --- a/Firestore/core/test/unit/testutil/expression_test_util.h +++ b/Firestore/core/test/unit/testutil/expression_test_util.h @@ -445,19 +445,27 @@ struct ComparisonValueTestData { results.push_back({value, value}); } - results.push_back({SharedConstant(-42LL), SharedConstant(-42.0)}); - results.push_back({SharedConstant(-42.0), SharedConstant(-42LL)}); - results.push_back({SharedConstant(42LL), SharedConstant(42.0)}); - results.push_back({SharedConstant(42.0), SharedConstant(42LL)}); + results.push_back( + {SharedConstant(static_cast(-42LL)), SharedConstant(-42.0)}); + results.push_back( + {SharedConstant(-42.0), SharedConstant(static_cast(-42LL))}); + results.push_back( + {SharedConstant(static_cast(42LL)), SharedConstant(42.0)}); + results.push_back( + {SharedConstant(42.0), SharedConstant(static_cast(42LL))}); results.push_back({SharedConstant(0.0), SharedConstant(-0.0)}); results.push_back({SharedConstant(-0.0), SharedConstant(0.0)}); - results.push_back({SharedConstant(0LL), SharedConstant(-0.0)}); - results.push_back({SharedConstant(-0.0), SharedConstant(0LL)}); + results.push_back( + {SharedConstant(static_cast(0LL)), SharedConstant(-0.0)}); + results.push_back( + {SharedConstant(-0.0), SharedConstant(static_cast(0LL))}); - results.push_back({SharedConstant(0LL), SharedConstant(0.0)}); - results.push_back({SharedConstant(0.0), SharedConstant(0LL)}); + results.push_back( + {SharedConstant(static_cast(0LL)), SharedConstant(0.0)}); + results.push_back( + {SharedConstant(0.0), SharedConstant(static_cast(0LL))}); return results; } From c2572ebdec97d70df7db258517e620c4a471d009 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 12 Nov 2025 13:11:50 -0500 Subject: [PATCH 07/36] fix type error 2 --- .../unit/core/expressions/arithmetic_test.cc | 266 +++++++++++------- .../test/unit/core/expressions/array_test.cc | 6 +- .../unit/core/expressions/comparison_test.cc | 3 +- .../test/unit/core/expressions/debug_test.cc | 5 +- .../expressions/mirroring_semantics_test.cc | 6 +- .../test/unit/core/expressions/string_test.cc | 100 ++++--- .../unit/core/expressions/timestamp_test.cc | 188 +++++++------ .../core/pipeline/collection_group_test.cc | 8 +- .../unit/core/pipeline/collection_test.cc | 8 +- .../test/unit/core/pipeline/complex_test.cc | 15 +- .../unit/testutil/expression_test_util.cc | 11 +- 11 files changed, 351 insertions(+), 265 deletions(-) diff --git a/Firestore/core/test/unit/core/expressions/arithmetic_test.cc b/Firestore/core/test/unit/core/expressions/arithmetic_test.cc index 1364fd6c38a..bf338cb3547 100644 --- a/Firestore/core/test/unit/core/expressions/arithmetic_test.cc +++ b/Firestore/core/test/unit/core/expressions/arithmetic_test.cc @@ -67,13 +67,15 @@ class ModFunctionTest : public ArithmeticExpressionsTest {}; TEST_F(AddFunctionTest, BasicNumerics) { EXPECT_THAT( - EvaluateExpr(*AddExpr({SharedConstant(1LL), SharedConstant(2LL)})), + EvaluateExpr(*AddExpr({SharedConstant(static_cast(1LL)), + SharedConstant(static_cast(2LL))})), Returns(Value(3LL))); + EXPECT_THAT(EvaluateExpr(*AddExpr({SharedConstant(static_cast(1LL)), + SharedConstant(2.5)})), + Returns(Value(3.5))); EXPECT_THAT( - EvaluateExpr(*AddExpr({SharedConstant(1LL), SharedConstant(2.5)})), - Returns(Value(3.5))); - EXPECT_THAT( - EvaluateExpr(*AddExpr({SharedConstant(1.0), SharedConstant(2LL)})), + EvaluateExpr(*AddExpr( + {SharedConstant(1.0), SharedConstant(static_cast(2LL))})), Returns(Value(3.0))); EXPECT_THAT( EvaluateExpr(*AddExpr({SharedConstant(1.0), SharedConstant(2.0)})), @@ -81,9 +83,9 @@ TEST_F(AddFunctionTest, BasicNumerics) { } TEST_F(AddFunctionTest, BasicNonNumerics) { - EXPECT_THAT( - EvaluateExpr(*AddExpr({SharedConstant(1LL), SharedConstant("1")})), - ReturnsError()); + EXPECT_THAT(EvaluateExpr(*AddExpr({SharedConstant(static_cast(1LL)), + SharedConstant("1")})), + ReturnsError()); EXPECT_THAT( EvaluateExpr(*AddExpr({SharedConstant("1"), SharedConstant(1.0)})), ReturnsError()); @@ -95,12 +97,14 @@ TEST_F(AddFunctionTest, BasicNonNumerics) { TEST_F(AddFunctionTest, DoubleLongAdditionOverflow) { // Note: C++ double can represent Long.MAX_VALUE + 1.0 exactly, unlike some JS // representations. - EXPECT_THAT(EvaluateExpr(*AddExpr({SharedConstant(9223372036854775807LL), - SharedConstant(1.0)})), + EXPECT_THAT(EvaluateExpr(*AddExpr( + {SharedConstant(static_cast(9223372036854775807LL)), + SharedConstant(1.0)})), Returns(Value(9.223372036854776e+18))); - EXPECT_THAT(EvaluateExpr(*AddExpr({SharedConstant(9.223372036854776e+18), - SharedConstant(100LL)})), - Returns(Value(9.223372036854776e+18 + 100.0))); + EXPECT_THAT( + EvaluateExpr(*AddExpr({SharedConstant(9.223372036854776e+18), + SharedConstant(static_cast(100LL))})), + Returns(Value(9.223372036854776e+18 + 100.0))); } TEST_F(AddFunctionTest, DoubleAdditionOverflow) { @@ -124,31 +128,33 @@ TEST_F(AddFunctionTest, SumPosAndNegInfinityReturnNaN) { TEST_F(AddFunctionTest, LongAdditionOverflow) { EXPECT_THAT(EvaluateExpr( *AddExpr({SharedConstant(std::numeric_limits::max()), - SharedConstant(1LL)})), + SharedConstant(static_cast(1LL))})), ReturnsError()); // Expect error due to overflow EXPECT_THAT(EvaluateExpr( *AddExpr({SharedConstant(std::numeric_limits::min()), - SharedConstant(-1LL)})), + SharedConstant(static_cast(-1LL))})), ReturnsError()); // Expect error due to overflow EXPECT_THAT(EvaluateExpr(*AddExpr( - {SharedConstant(1LL), + {SharedConstant(static_cast(1LL)), SharedConstant(std::numeric_limits::max())})), ReturnsError()); // Expect error due to overflow } TEST_F(AddFunctionTest, NanNumberReturnNaN) { double nan_val = std::numeric_limits::quiet_NaN(); - EXPECT_THAT( - EvaluateExpr(*AddExpr({SharedConstant(1LL), SharedConstant(nan_val)})), - Returns(Value(nan_val))); + EXPECT_THAT(EvaluateExpr(*AddExpr({SharedConstant(static_cast(1LL)), + SharedConstant(nan_val)})), + Returns(Value(nan_val))); EXPECT_THAT( EvaluateExpr(*AddExpr({SharedConstant(1.0), SharedConstant(nan_val)})), Returns(Value(nan_val))); - EXPECT_THAT(EvaluateExpr(*AddExpr({SharedConstant(9007199254740991LL), - SharedConstant(nan_val)})), + EXPECT_THAT(EvaluateExpr(*AddExpr( + {SharedConstant(static_cast(9007199254740991LL)), + SharedConstant(nan_val)})), Returns(Value(nan_val))); - EXPECT_THAT(EvaluateExpr(*AddExpr({SharedConstant(-9007199254740991LL), - SharedConstant(nan_val)})), + EXPECT_THAT(EvaluateExpr(*AddExpr( + {SharedConstant(static_cast(-9007199254740991LL)), + SharedConstant(nan_val)})), Returns(Value(nan_val))); EXPECT_THAT( EvaluateExpr(*AddExpr({SharedConstant(std::numeric_limits::max()), @@ -177,12 +183,16 @@ TEST_F(AddFunctionTest, NanNotNumberTypeReturnError) { TEST_F(AddFunctionTest, MultiArgument) { // EvaluateExpr handles single expression, so nest calls for multi-arg - auto add12 = AddExpr({SharedConstant(1LL), SharedConstant(2LL)}); - EXPECT_THAT(EvaluateExpr(*AddExpr({add12, SharedConstant(3LL)})), + auto add12 = AddExpr({SharedConstant(static_cast(1LL)), + SharedConstant(static_cast(2LL))}); + EXPECT_THAT(EvaluateExpr( + *AddExpr({add12, SharedConstant(static_cast(3LL))})), Returns(Value(6LL))); - auto add10_2 = AddExpr({SharedConstant(1.0), SharedConstant(2LL)}); - EXPECT_THAT(EvaluateExpr(*AddExpr({add10_2, SharedConstant(3LL)})), + auto add10_2 = + AddExpr({SharedConstant(1.0), SharedConstant(static_cast(2LL))}); + EXPECT_THAT(EvaluateExpr(*AddExpr( + {add10_2, SharedConstant(static_cast(3LL))})), Returns(Value(6.0))); } @@ -190,13 +200,16 @@ TEST_F(AddFunctionTest, MultiArgument) { TEST_F(SubtractFunctionTest, BasicNumerics) { EXPECT_THAT( - EvaluateExpr(*SubtractExpr({SharedConstant(1LL), SharedConstant(2LL)})), + EvaluateExpr(*SubtractExpr({SharedConstant(static_cast(1LL)), + SharedConstant(static_cast(2LL))})), Returns(Value(-1LL))); EXPECT_THAT( - EvaluateExpr(*SubtractExpr({SharedConstant(1LL), SharedConstant(2.5)})), + EvaluateExpr(*SubtractExpr( + {SharedConstant(static_cast(1LL)), SharedConstant(2.5)})), Returns(Value(-1.5))); EXPECT_THAT( - EvaluateExpr(*SubtractExpr({SharedConstant(1.0), SharedConstant(2LL)})), + EvaluateExpr(*SubtractExpr( + {SharedConstant(1.0), SharedConstant(static_cast(2LL))})), Returns(Value(-1.0))); EXPECT_THAT( EvaluateExpr(*SubtractExpr({SharedConstant(1.0), SharedConstant(2.0)})), @@ -205,7 +218,8 @@ TEST_F(SubtractFunctionTest, BasicNumerics) { TEST_F(SubtractFunctionTest, BasicNonNumerics) { EXPECT_THAT( - EvaluateExpr(*SubtractExpr({SharedConstant(1LL), SharedConstant("1")})), + EvaluateExpr(*SubtractExpr( + {SharedConstant(static_cast(1LL)), SharedConstant("1")})), ReturnsError()); EXPECT_THAT( EvaluateExpr(*SubtractExpr({SharedConstant("1"), SharedConstant(1.0)})), @@ -229,27 +243,30 @@ TEST_F(SubtractFunctionTest, DoubleSubtractionOverflow) { TEST_F(SubtractFunctionTest, LongSubtractionOverflow) { EXPECT_THAT(EvaluateExpr(*SubtractExpr( {SharedConstant(std::numeric_limits::min()), - SharedConstant(1LL)})), + SharedConstant(static_cast(1LL))})), ReturnsError()); EXPECT_THAT(EvaluateExpr(*SubtractExpr( {SharedConstant(std::numeric_limits::max()), - SharedConstant(-1LL)})), + SharedConstant(static_cast(-1LL))})), ReturnsError()); } TEST_F(SubtractFunctionTest, NanNumberReturnNaN) { double nan_val = std::numeric_limits::quiet_NaN(); - EXPECT_THAT(EvaluateExpr(*SubtractExpr( - {SharedConstant(1LL), SharedConstant(nan_val)})), - Returns(Value(nan_val))); + EXPECT_THAT( + EvaluateExpr(*SubtractExpr({SharedConstant(static_cast(1LL)), + SharedConstant(nan_val)})), + Returns(Value(nan_val))); EXPECT_THAT(EvaluateExpr(*SubtractExpr( {SharedConstant(1.0), SharedConstant(nan_val)})), Returns(Value(nan_val))); - EXPECT_THAT(EvaluateExpr(*SubtractExpr({SharedConstant(9007199254740991LL), - SharedConstant(nan_val)})), + EXPECT_THAT(EvaluateExpr(*SubtractExpr( + {SharedConstant(static_cast(9007199254740991LL)), + SharedConstant(nan_val)})), Returns(Value(nan_val))); - EXPECT_THAT(EvaluateExpr(*SubtractExpr({SharedConstant(-9007199254740991LL), - SharedConstant(nan_val)})), + EXPECT_THAT(EvaluateExpr(*SubtractExpr( + {SharedConstant(static_cast(-9007199254740991LL)), + SharedConstant(nan_val)})), Returns(Value(nan_val))); EXPECT_THAT(EvaluateExpr(*SubtractExpr( {SharedConstant(std::numeric_limits::max()), @@ -279,10 +296,10 @@ TEST_F(SubtractFunctionTest, NanNotNumberTypeReturnError) { TEST_F(SubtractFunctionTest, PositiveInfinity) { EXPECT_THAT(EvaluateExpr(*SubtractExpr( {SharedConstant(std::numeric_limits::infinity()), - SharedConstant(1LL)})), + SharedConstant(static_cast(1LL))})), Returns(Value(std::numeric_limits::infinity()))); EXPECT_THAT(EvaluateExpr(*SubtractExpr( - {SharedConstant(1LL), + {SharedConstant(static_cast(1LL)), SharedConstant(std::numeric_limits::infinity())})), Returns(Value(-std::numeric_limits::infinity()))); } @@ -290,10 +307,10 @@ TEST_F(SubtractFunctionTest, PositiveInfinity) { TEST_F(SubtractFunctionTest, NegativeInfinity) { EXPECT_THAT(EvaluateExpr(*SubtractExpr( {SharedConstant(-std::numeric_limits::infinity()), - SharedConstant(1LL)})), + SharedConstant(static_cast(1LL))})), Returns(Value(-std::numeric_limits::infinity()))); EXPECT_THAT(EvaluateExpr(*SubtractExpr( - {SharedConstant(1LL), + {SharedConstant(static_cast(1LL)), SharedConstant(-std::numeric_limits::infinity())})), Returns(Value(std::numeric_limits::infinity()))); } @@ -313,13 +330,16 @@ TEST_F(SubtractFunctionTest, PositiveInfinityNegativeInfinity) { TEST_F(MultiplyFunctionTest, BasicNumerics) { EXPECT_THAT( - EvaluateExpr(*MultiplyExpr({SharedConstant(1LL), SharedConstant(2LL)})), + EvaluateExpr(*MultiplyExpr({SharedConstant(static_cast(1LL)), + SharedConstant(static_cast(2LL))})), Returns(Value(2LL))); EXPECT_THAT( - EvaluateExpr(*MultiplyExpr({SharedConstant(3LL), SharedConstant(2.5)})), + EvaluateExpr(*MultiplyExpr( + {SharedConstant(static_cast(3LL)), SharedConstant(2.5)})), Returns(Value(7.5))); EXPECT_THAT( - EvaluateExpr(*MultiplyExpr({SharedConstant(1.0), SharedConstant(2LL)})), + EvaluateExpr(*MultiplyExpr( + {SharedConstant(1.0), SharedConstant(static_cast(2LL))})), Returns(Value(2.0))); EXPECT_THAT( EvaluateExpr(*MultiplyExpr({SharedConstant(1.32), SharedConstant(2.0)})), @@ -328,7 +348,8 @@ TEST_F(MultiplyFunctionTest, BasicNumerics) { TEST_F(MultiplyFunctionTest, BasicNonNumerics) { EXPECT_THAT( - EvaluateExpr(*MultiplyExpr({SharedConstant(1LL), SharedConstant("1")})), + EvaluateExpr(*MultiplyExpr( + {SharedConstant(static_cast(1LL)), SharedConstant("1")})), ReturnsError()); EXPECT_THAT( EvaluateExpr(*MultiplyExpr({SharedConstant("1"), SharedConstant(1.0)})), @@ -340,11 +361,13 @@ TEST_F(MultiplyFunctionTest, BasicNonNumerics) { TEST_F(MultiplyFunctionTest, DoubleLongMultiplicationOverflow) { // C++ double handles this fine - EXPECT_THAT(EvaluateExpr(*MultiplyExpr({SharedConstant(9223372036854775807LL), - SharedConstant(100.0)})), + EXPECT_THAT(EvaluateExpr(*MultiplyExpr( + {SharedConstant(static_cast(9223372036854775807LL)), + SharedConstant(100.0)})), Returns(Value(9.223372036854776e+20))); // Approx - EXPECT_THAT(EvaluateExpr(*MultiplyExpr({SharedConstant(9223372036854775807LL), - SharedConstant(100LL)})), + EXPECT_THAT(EvaluateExpr(*MultiplyExpr( + {SharedConstant(static_cast(9223372036854775807LL)), + SharedConstant(static_cast(100LL))})), ReturnsError()); // Integer overflow } @@ -362,36 +385,39 @@ TEST_F(MultiplyFunctionTest, DoubleMultiplicationOverflow) { TEST_F(MultiplyFunctionTest, LongMultiplicationOverflow) { EXPECT_THAT(EvaluateExpr(*MultiplyExpr( {SharedConstant(std::numeric_limits::max()), - SharedConstant(10LL)})), + SharedConstant(static_cast(10LL))})), ReturnsError()); EXPECT_THAT(EvaluateExpr(*MultiplyExpr( {SharedConstant(std::numeric_limits::min()), - SharedConstant(10LL)})), + SharedConstant(static_cast(10LL))})), ReturnsError()); EXPECT_THAT(EvaluateExpr(*MultiplyExpr( - {SharedConstant(-10LL), + {SharedConstant(static_cast(-10LL)), SharedConstant(std::numeric_limits::max())})), ReturnsError()); // Note: min * -10 overflows EXPECT_THAT(EvaluateExpr(*MultiplyExpr( - {SharedConstant(-10LL), + {SharedConstant(static_cast(-10LL)), SharedConstant(std::numeric_limits::min())})), ReturnsError()); } TEST_F(MultiplyFunctionTest, NanNumberReturnNaN) { double nan_val = std::numeric_limits::quiet_NaN(); - EXPECT_THAT(EvaluateExpr(*MultiplyExpr( - {SharedConstant(1LL), SharedConstant(nan_val)})), - Returns(Value(nan_val))); + EXPECT_THAT( + EvaluateExpr(*MultiplyExpr({SharedConstant(static_cast(1LL)), + SharedConstant(nan_val)})), + Returns(Value(nan_val))); EXPECT_THAT(EvaluateExpr(*MultiplyExpr( {SharedConstant(1.0), SharedConstant(nan_val)})), Returns(Value(nan_val))); - EXPECT_THAT(EvaluateExpr(*MultiplyExpr({SharedConstant(9007199254740991LL), - SharedConstant(nan_val)})), + EXPECT_THAT(EvaluateExpr(*MultiplyExpr( + {SharedConstant(static_cast(9007199254740991LL)), + SharedConstant(nan_val)})), Returns(Value(nan_val))); - EXPECT_THAT(EvaluateExpr(*MultiplyExpr({SharedConstant(-9007199254740991LL), - SharedConstant(nan_val)})), + EXPECT_THAT(EvaluateExpr(*MultiplyExpr( + {SharedConstant(static_cast(-9007199254740991LL)), + SharedConstant(nan_val)})), Returns(Value(nan_val))); EXPECT_THAT(EvaluateExpr(*MultiplyExpr( {SharedConstant(std::numeric_limits::max()), @@ -421,10 +447,10 @@ TEST_F(MultiplyFunctionTest, NanNotNumberTypeReturnError) { TEST_F(MultiplyFunctionTest, PositiveInfinity) { EXPECT_THAT(EvaluateExpr(*MultiplyExpr( {SharedConstant(std::numeric_limits::infinity()), - SharedConstant(1LL)})), + SharedConstant(static_cast(1LL))})), Returns(Value(std::numeric_limits::infinity()))); EXPECT_THAT(EvaluateExpr(*MultiplyExpr( - {SharedConstant(1LL), + {SharedConstant(static_cast(1LL)), SharedConstant(std::numeric_limits::infinity())})), Returns(Value(std::numeric_limits::infinity()))); } @@ -432,10 +458,10 @@ TEST_F(MultiplyFunctionTest, PositiveInfinity) { TEST_F(MultiplyFunctionTest, NegativeInfinity) { EXPECT_THAT(EvaluateExpr(*MultiplyExpr( {SharedConstant(-std::numeric_limits::infinity()), - SharedConstant(1LL)})), + SharedConstant(static_cast(1LL))})), Returns(Value(-std::numeric_limits::infinity()))); EXPECT_THAT(EvaluateExpr(*MultiplyExpr( - {SharedConstant(1LL), + {SharedConstant(static_cast(1LL)), SharedConstant(-std::numeric_limits::infinity())})), Returns(Value(-std::numeric_limits::infinity()))); } @@ -453,11 +479,14 @@ TEST_F(MultiplyFunctionTest, } TEST_F(MultiplyFunctionTest, MultiArgument) { - auto mult12 = MultiplyExpr({SharedConstant(1LL), SharedConstant(2LL)}); - EXPECT_THAT(EvaluateExpr(*MultiplyExpr({mult12, SharedConstant(3LL)})), + auto mult12 = MultiplyExpr({SharedConstant(static_cast(1LL)), + SharedConstant(static_cast(2LL))}); + EXPECT_THAT(EvaluateExpr(*MultiplyExpr( + {mult12, SharedConstant(static_cast(3LL))})), Returns(Value(6LL))); - auto mult23 = MultiplyExpr({SharedConstant(2LL), SharedConstant(3LL)}); + auto mult23 = MultiplyExpr({SharedConstant(static_cast(2LL)), + SharedConstant(static_cast(3LL))}); EXPECT_THAT(EvaluateExpr(*MultiplyExpr({SharedConstant(1.0), mult23})), Returns(Value(6.0))); } @@ -466,13 +495,16 @@ TEST_F(MultiplyFunctionTest, MultiArgument) { TEST_F(DivideFunctionTest, BasicNumerics) { EXPECT_THAT( - EvaluateExpr(*DivideExpr({SharedConstant(10LL), SharedConstant(2LL)})), + EvaluateExpr(*DivideExpr({SharedConstant(static_cast(10LL)), + SharedConstant(static_cast(2LL))})), Returns(Value(5LL))); EXPECT_THAT( - EvaluateExpr(*DivideExpr({SharedConstant(10LL), SharedConstant(2.0)})), + EvaluateExpr(*DivideExpr( + {SharedConstant(static_cast(10LL)), SharedConstant(2.0)})), Returns(Value(5.0))); EXPECT_THAT( - EvaluateExpr(*DivideExpr({SharedConstant(10.0), SharedConstant(3LL)})), + EvaluateExpr(*DivideExpr( + {SharedConstant(10.0), SharedConstant(static_cast(3LL))})), Returns(Value(10.0 / 3.0))); EXPECT_THAT( EvaluateExpr(*DivideExpr({SharedConstant(10.0), SharedConstant(7.0)})), @@ -481,7 +513,8 @@ TEST_F(DivideFunctionTest, BasicNumerics) { TEST_F(DivideFunctionTest, BasicNonNumerics) { EXPECT_THAT( - EvaluateExpr(*DivideExpr({SharedConstant(1LL), SharedConstant("1")})), + EvaluateExpr(*DivideExpr( + {SharedConstant(static_cast(1LL)), SharedConstant("1")})), ReturnsError()); EXPECT_THAT( EvaluateExpr(*DivideExpr({SharedConstant("1"), SharedConstant(1.0)})), @@ -493,16 +526,20 @@ TEST_F(DivideFunctionTest, BasicNonNumerics) { TEST_F(DivideFunctionTest, LongDivision) { EXPECT_THAT( - EvaluateExpr(*DivideExpr({SharedConstant(10LL), SharedConstant(3LL)})), + EvaluateExpr(*DivideExpr({SharedConstant(static_cast(10LL)), + SharedConstant(static_cast(3LL))})), Returns(Value(3LL))); // Integer division EXPECT_THAT( - EvaluateExpr(*DivideExpr({SharedConstant(-10LL), SharedConstant(3LL)})), + EvaluateExpr(*DivideExpr({SharedConstant(static_cast(-10LL)), + SharedConstant(static_cast(3LL))})), Returns(Value(-3LL))); // Integer division EXPECT_THAT( - EvaluateExpr(*DivideExpr({SharedConstant(10LL), SharedConstant(-3LL)})), + EvaluateExpr(*DivideExpr({SharedConstant(static_cast(10LL)), + SharedConstant(static_cast(-3LL))})), Returns(Value(-3LL))); // Integer division EXPECT_THAT( - EvaluateExpr(*DivideExpr({SharedConstant(-10LL), SharedConstant(-3LL)})), + EvaluateExpr(*DivideExpr({SharedConstant(static_cast(-10LL)), + SharedConstant(static_cast(-3LL))})), Returns(Value(3LL))); // Integer division } @@ -519,7 +556,8 @@ TEST_F(DivideFunctionTest, DoubleDivisionOverflow) { TEST_F(DivideFunctionTest, ByZero) { EXPECT_THAT( - EvaluateExpr(*DivideExpr({SharedConstant(1LL), SharedConstant(0LL)})), + EvaluateExpr(*DivideExpr({SharedConstant(static_cast(1LL)), + SharedConstant(static_cast(0LL))})), ReturnsError()); // Integer division by zero is error EXPECT_THAT( EvaluateExpr(*DivideExpr({SharedConstant(1.1), SharedConstant(0.0)})), @@ -535,10 +573,12 @@ TEST_F(DivideFunctionTest, ByZero) { TEST_F(DivideFunctionTest, NanNumberReturnNaN) { double nan_val = std::numeric_limits::quiet_NaN(); EXPECT_THAT( - EvaluateExpr(*DivideExpr({SharedConstant(1LL), SharedConstant(nan_val)})), + EvaluateExpr(*DivideExpr({SharedConstant(static_cast(1LL)), + SharedConstant(nan_val)})), Returns(Value(nan_val))); EXPECT_THAT( - EvaluateExpr(*DivideExpr({SharedConstant(nan_val), SharedConstant(1LL)})), + EvaluateExpr(*DivideExpr({SharedConstant(nan_val), + SharedConstant(static_cast(1LL))})), Returns(Value(nan_val))); EXPECT_THAT( EvaluateExpr(*DivideExpr({SharedConstant(1.0), SharedConstant(nan_val)})), @@ -573,10 +613,10 @@ TEST_F(DivideFunctionTest, NanNotNumberTypeReturnError) { TEST_F(DivideFunctionTest, PositiveInfinity) { EXPECT_THAT(EvaluateExpr(*DivideExpr( {SharedConstant(std::numeric_limits::infinity()), - SharedConstant(1LL)})), + SharedConstant(static_cast(1LL))})), Returns(Value(std::numeric_limits::infinity()))); EXPECT_THAT(EvaluateExpr(*DivideExpr( - {SharedConstant(1LL), + {SharedConstant(static_cast(1LL)), SharedConstant(std::numeric_limits::infinity())})), Returns(Value(0.0))); } @@ -584,10 +624,10 @@ TEST_F(DivideFunctionTest, PositiveInfinity) { TEST_F(DivideFunctionTest, NegativeInfinity) { EXPECT_THAT(EvaluateExpr(*DivideExpr( {SharedConstant(-std::numeric_limits::infinity()), - SharedConstant(1LL)})), + SharedConstant(static_cast(1LL))})), Returns(Value(-std::numeric_limits::infinity()))); EXPECT_THAT(EvaluateExpr(*DivideExpr( - {SharedConstant(1LL), + {SharedConstant(static_cast(1LL)), SharedConstant(-std::numeric_limits::infinity())})), Returns(Value(-0.0))); // Note: -0.0 } @@ -607,7 +647,8 @@ TEST_F(DivideFunctionTest, PositiveInfinityNegativeInfinityReturnsNan) { TEST_F(ModFunctionTest, DivisorZeroThrowsError) { EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(42LL), SharedConstant(0LL)})), + EvaluateExpr(*ModExpr( + {SharedConstant(42LL), SharedConstant(static_cast(0LL))})), ReturnsError()); // Note: C++ doesn't distinguish -0LL from 0LL // EXPECT_TRUE(AssertResultEquals( @@ -624,9 +665,9 @@ TEST_F(ModFunctionTest, DivisorZeroThrowsError) { } TEST_F(ModFunctionTest, DividendZeroReturnsZero) { - EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(0LL), SharedConstant(42LL)})), - Returns(Value(0LL))); + EXPECT_THAT(EvaluateExpr(*ModExpr({SharedConstant(static_cast(0LL)), + SharedConstant(42LL)})), + Returns(Value(0LL))); // Note: C++ doesn't distinguish -0LL from 0LL // EXPECT_THAT( // EvaluateExpr(*ModExpr({SharedConstant(-0LL), SharedConstant(42LL)})), @@ -642,25 +683,29 @@ TEST_F(ModFunctionTest, DividendZeroReturnsZero) { TEST_F(ModFunctionTest, LongPositivePositive) { EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(10LL), SharedConstant(3LL)})), + EvaluateExpr(*ModExpr({SharedConstant(static_cast(10LL)), + SharedConstant(static_cast(3LL))})), Returns(Value(1LL))); } TEST_F(ModFunctionTest, LongNegativeNegative) { EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(-10LL), SharedConstant(-3LL)})), + EvaluateExpr(*ModExpr({SharedConstant(static_cast(-10LL)), + SharedConstant(static_cast(-3LL))})), Returns(Value(-1LL))); // C++ % behavior } TEST_F(ModFunctionTest, LongPositiveNegative) { EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(10LL), SharedConstant(-3LL)})), + EvaluateExpr(*ModExpr({SharedConstant(static_cast(10LL)), + SharedConstant(static_cast(-3LL))})), Returns(Value(1LL))); // C++ % behavior } TEST_F(ModFunctionTest, LongNegativePositive) { EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(-10LL), SharedConstant(3LL)})), + EvaluateExpr(*ModExpr({SharedConstant(static_cast(-10LL)), + SharedConstant(static_cast(3LL))})), Returns(Value(-1LL))); // C++ % behavior } @@ -694,16 +739,20 @@ TEST_F(ModFunctionTest, DoubleNegativePositive) { TEST_F(ModFunctionTest, LongPerfectlyDivisible) { EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(10LL), SharedConstant(5LL)})), + EvaluateExpr(*ModExpr({SharedConstant(static_cast(10LL)), + SharedConstant(static_cast(5LL))})), Returns(Value(0LL))); EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(-10LL), SharedConstant(5LL)})), + EvaluateExpr(*ModExpr({SharedConstant(static_cast(-10LL)), + SharedConstant(static_cast(5LL))})), Returns(Value(0LL))); EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(10LL), SharedConstant(-5LL)})), + EvaluateExpr(*ModExpr({SharedConstant(static_cast(10LL)), + SharedConstant(static_cast(-5LL))})), Returns(Value(0LL))); EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(-10LL), SharedConstant(-5LL)})), + EvaluateExpr(*ModExpr({SharedConstant(static_cast(-10LL)), + SharedConstant(static_cast(-5LL))})), Returns(Value(0LL))); } @@ -723,11 +772,12 @@ TEST_F(ModFunctionTest, DoublePerfectlyDivisible) { } TEST_F(ModFunctionTest, NonNumericsReturnError) { + EXPECT_THAT(EvaluateExpr(*ModExpr({SharedConstant(static_cast(10LL)), + SharedConstant("1")})), + ReturnsError()); EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(10LL), SharedConstant("1")})), - ReturnsError()); - EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant("1"), SharedConstant(10LL)})), + EvaluateExpr(*ModExpr( + {SharedConstant("1"), SharedConstant(static_cast(10LL))})), ReturnsError()); EXPECT_THAT( EvaluateExpr(*ModExpr({SharedConstant("1"), SharedConstant("1")})), @@ -736,9 +786,9 @@ TEST_F(ModFunctionTest, NonNumericsReturnError) { TEST_F(ModFunctionTest, NanNumberReturnNaN) { double nan_val = std::numeric_limits::quiet_NaN(); - EXPECT_THAT( - EvaluateExpr(*ModExpr({SharedConstant(1LL), SharedConstant(nan_val)})), - Returns(Value(nan_val))); + EXPECT_THAT(EvaluateExpr(*ModExpr({SharedConstant(static_cast(1LL)), + SharedConstant(nan_val)})), + Returns(Value(nan_val))); EXPECT_THAT( EvaluateExpr(*ModExpr({SharedConstant(1.0), SharedConstant(nan_val)})), Returns(Value(nan_val))); @@ -761,7 +811,7 @@ TEST_F(ModFunctionTest, NanNotNumberTypeReturnError) { TEST_F(ModFunctionTest, NumberPosInfinityReturnSelf) { EXPECT_THAT(EvaluateExpr(*ModExpr( - {SharedConstant(1LL), + {SharedConstant(static_cast(1LL)), SharedConstant(std::numeric_limits::infinity())})), Returns(Value(1.0))); // fmod(1, inf) -> 1 EXPECT_THAT(EvaluateExpr(*ModExpr( @@ -777,7 +827,7 @@ TEST_F(ModFunctionTest, NumberPosInfinityReturnSelf) { TEST_F(ModFunctionTest, PosInfinityNumberReturnNaN) { EXPECT_THAT(EvaluateExpr(*ModExpr( {SharedConstant(std::numeric_limits::infinity()), - SharedConstant(1LL)})), + SharedConstant(static_cast(1LL))})), Returns(Value(std::numeric_limits::quiet_NaN()))); EXPECT_THAT(EvaluateExpr(*ModExpr( {SharedConstant(std::numeric_limits::infinity()), @@ -791,7 +841,7 @@ TEST_F(ModFunctionTest, PosInfinityNumberReturnNaN) { TEST_F(ModFunctionTest, NumberNegInfinityReturnSelf) { EXPECT_THAT(EvaluateExpr(*ModExpr( - {SharedConstant(1LL), + {SharedConstant(static_cast(1LL)), SharedConstant(-std::numeric_limits::infinity())})), Returns(Value(1.0))); // fmod(1, -inf) -> 1 EXPECT_THAT(EvaluateExpr(*ModExpr( @@ -807,7 +857,7 @@ TEST_F(ModFunctionTest, NumberNegInfinityReturnSelf) { TEST_F(ModFunctionTest, NegInfinityNumberReturnNaN) { EXPECT_THAT(EvaluateExpr(*ModExpr( {SharedConstant(-std::numeric_limits::infinity()), - SharedConstant(1LL)})), + SharedConstant(static_cast(1LL))})), Returns(Value(std::numeric_limits::quiet_NaN()))); EXPECT_THAT(EvaluateExpr(*ModExpr( {SharedConstant(-std::numeric_limits::infinity()), diff --git a/Firestore/core/test/unit/core/expressions/array_test.cc b/Firestore/core/test/unit/core/expressions/array_test.cc index dd77d14c2bb..80e6e1ee892 100644 --- a/Firestore/core/test/unit/core/expressions/array_test.cc +++ b/Firestore/core/test/unit/core/expressions/array_test.cc @@ -250,7 +250,8 @@ TEST_F(ArrayContainsTest, ValueNotFoundInArray) { auto array_to_search = SharedConstant(Array(Value(42LL), Value("matang"), Value(true))); EXPECT_THAT( - EvaluateExpr(*ArrayContainsExpr({array_to_search, SharedConstant(4LL)})), + EvaluateExpr(*ArrayContainsExpr( + {array_to_search, SharedConstant(static_cast(4LL))})), Returns(Value(false))); } @@ -362,7 +363,8 @@ TEST_F(ArrayLengthTest, NotArrayTypeReturnsError) { // Test with other non-array types. EXPECT_THAT(EvaluateExpr(*ArrayLengthExpr({SharedConstant("notAnArray")})), ReturnsError()); - EXPECT_THAT(EvaluateExpr(*ArrayLengthExpr({SharedConstant(123LL)})), + EXPECT_THAT(EvaluateExpr(*ArrayLengthExpr( + {SharedConstant(static_cast(123LL))})), ReturnsError()); EXPECT_THAT(EvaluateExpr(*ArrayLengthExpr({SharedConstant(true)})), ReturnsError()); diff --git a/Firestore/core/test/unit/core/expressions/comparison_test.cc b/Firestore/core/test/unit/core/expressions/comparison_test.cc index c3d4de483fe..1113fd5d4b6 100644 --- a/Firestore/core/test/unit/core/expressions/comparison_test.cc +++ b/Firestore/core/test/unit/core/expressions/comparison_test.cc @@ -206,7 +206,8 @@ TEST_F(EqFunctionTest, NaNComparisonsReturnFalse) { // eq.null_missingInMap_equality TEST_F(EqFunctionTest, NullContainerEquality) { auto null_array = SharedConstant(testutil::Array(testutil::Value(nullptr))); - EXPECT_THAT(EvaluateExpr(*EqExpr({null_array, SharedConstant(1LL)})), + EXPECT_THAT(EvaluateExpr(*EqExpr( + {null_array, SharedConstant(static_cast(1LL))})), Returns(testutil::Value(false))); EXPECT_THAT(EvaluateExpr(*EqExpr({null_array, SharedConstant("1")})), Returns(testutil::Value(false))); diff --git a/Firestore/core/test/unit/core/expressions/debug_test.cc b/Firestore/core/test/unit/core/expressions/debug_test.cc index 9b6ed4df06a..ae527a16573 100644 --- a/Firestore/core/test/unit/core/expressions/debug_test.cc +++ b/Firestore/core/test/unit/core/expressions/debug_test.cc @@ -117,8 +117,9 @@ TEST_F(DebugTest, IsErrorFieldMissingReturnsFalse) { } TEST_F(DebugTest, IsErrorNonErrorReturnsFalse) { - EXPECT_THAT(EvaluateExpr(*IsErrorExpr(SharedConstant(42LL))), - Returns(Value(false))); + EXPECT_THAT( + EvaluateExpr(*IsErrorExpr(SharedConstant(static_cast(42LL)))), + Returns(Value(false))); } TEST_F(DebugTest, IsErrorExplicitNullReturnsFalse) { diff --git a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc index 02a66579b84..e84c450a512 100644 --- a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc +++ b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc @@ -92,12 +92,14 @@ class MirroringSemanticsTest : public ::testing::Test { const std::shared_ptr NULL_INPUT = SharedConstant(nullptr); // Error: Integer division by zero const std::shared_ptr ERROR_INPUT = - DivideExpr({SharedConstant(1LL), SharedConstant(0LL)}); + DivideExpr({SharedConstant(static_cast(1LL)), + SharedConstant(static_cast(0LL))}); // Unset: Field that doesn't exist in the default test document const std::shared_ptr UNSET_INPUT = std::make_shared("non-existent-field"); // Valid: A simple valid input for binary tests - const std::shared_ptr VALID_INPUT = SharedConstant(42LL); + const std::shared_ptr VALID_INPUT = + SharedConstant(static_cast(42LL)); }; // --- Unary Function Tests --- diff --git a/Firestore/core/test/unit/core/expressions/string_test.cc b/Firestore/core/test/unit/core/expressions/string_test.cc index 17ca21fd914..404f9f1eb0a 100644 --- a/Firestore/core/test/unit/core/expressions/string_test.cc +++ b/Firestore/core/test/unit/core/expressions/string_test.cc @@ -83,7 +83,8 @@ TEST_F(ByteLengthTest, EmptyByte) { } TEST_F(ByteLengthTest, NonStringOrBytesReturnsError) { - EXPECT_THAT(EvaluateExpr(*ByteLengthExpr(SharedConstant(123LL))), + EXPECT_THAT(EvaluateExpr( + *ByteLengthExpr(SharedConstant(static_cast(123LL)))), ReturnsError()); EXPECT_THAT(EvaluateExpr(*ByteLengthExpr(SharedConstant(true))), ReturnsError()); @@ -352,7 +353,8 @@ TEST_F(StrConcatTest, MultipleStringChildrenReturnsCombination) { TEST_F(StrConcatTest, MultipleNonStringChildrenReturnsError) { EXPECT_THAT( - EvaluateExpr(*StrConcatExpr({SharedConstant("foo"), SharedConstant(42LL), + EvaluateExpr(*StrConcatExpr({SharedConstant("foo"), + SharedConstant(static_cast(42LL)), SharedConstant("bar")})), ReturnsError()); } @@ -392,15 +394,17 @@ TEST_F(StrConcatTest, LargeStrings) { // --- EndsWith Tests --- TEST_F(EndsWithTest, GetNonStringValueIsError) { - EXPECT_THAT(EvaluateExpr(*EndsWithExpr(SharedConstant(42LL), - SharedConstant("search"))), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*EndsWithExpr(SharedConstant(static_cast(42LL)), + SharedConstant("search"))), + ReturnsError()); } TEST_F(EndsWithTest, GetNonStringSuffixIsError) { - EXPECT_THAT(EvaluateExpr(*EndsWithExpr(SharedConstant("search"), - SharedConstant(42LL))), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*EndsWithExpr(SharedConstant("search"), + SharedConstant(static_cast(42LL)))), + ReturnsError()); } TEST_F(EndsWithTest, GetEmptyInputsReturnsTrue) { @@ -441,14 +445,15 @@ TEST_F(EndsWithTest, GetLargeSuffixReturnsFalse) { // --- Like Tests --- TEST_F(LikeTest, GetNonStringLikeIsError) { - EXPECT_THAT( - EvaluateExpr(*LikeExpr(SharedConstant(42LL), SharedConstant("search"))), - ReturnsError()); + EXPECT_THAT(EvaluateExpr(*LikeExpr(SharedConstant(static_cast(42LL)), + SharedConstant("search"))), + ReturnsError()); } TEST_F(LikeTest, GetNonStringValueIsError) { EXPECT_THAT( - EvaluateExpr(*LikeExpr(SharedConstant("ear"), SharedConstant(42LL))), + EvaluateExpr(*LikeExpr(SharedConstant("ear"), + SharedConstant(static_cast(42LL)))), ReturnsError()); } @@ -495,15 +500,17 @@ TEST_F(LikeTest, GetDynamicLike) { // --- RegexContains Tests --- TEST_F(RegexContainsTest, GetNonStringRegexIsError) { - EXPECT_THAT(EvaluateExpr(*RegexContainsExpr(SharedConstant(42LL), - SharedConstant("search"))), + EXPECT_THAT(EvaluateExpr( + *RegexContainsExpr(SharedConstant(static_cast(42LL)), + SharedConstant("search"))), ReturnsError()); } TEST_F(RegexContainsTest, GetNonStringValueIsError) { - EXPECT_THAT(EvaluateExpr(*RegexContainsExpr(SharedConstant("ear"), - SharedConstant(42LL))), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*RegexContainsExpr( + SharedConstant("ear"), SharedConstant(static_cast(42LL)))), + ReturnsError()); } TEST_F(RegexContainsTest, GetInvalidRegexIsError) { @@ -553,15 +560,17 @@ TEST_F(RegexContainsTest, GetDynamicRegex) { // --- RegexMatch Tests --- TEST_F(RegexMatchTest, GetNonStringRegexIsError) { - EXPECT_THAT(EvaluateExpr(*RegexMatchExpr(SharedConstant(42LL), - SharedConstant("search"))), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*RegexMatchExpr(SharedConstant(static_cast(42LL)), + SharedConstant("search"))), + ReturnsError()); } TEST_F(RegexMatchTest, GetNonStringValueIsError) { - EXPECT_THAT(EvaluateExpr( - *RegexMatchExpr(SharedConstant("ear"), SharedConstant(42LL))), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*RegexMatchExpr(SharedConstant("ear"), + SharedConstant(static_cast(42LL)))), + ReturnsError()); } TEST_F(RegexMatchTest, GetInvalidRegexIsError) { @@ -617,15 +626,17 @@ TEST_F(RegexMatchTest, GetDynamicRegex) { // --- StartsWith Tests --- TEST_F(StartsWithTest, GetNonStringValueIsError) { - EXPECT_THAT(EvaluateExpr(*StartsWithExpr(SharedConstant(42LL), - SharedConstant("search"))), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*StartsWithExpr(SharedConstant(static_cast(42LL)), + SharedConstant("search"))), + ReturnsError()); } TEST_F(StartsWithTest, GetNonStringPrefixIsError) { - EXPECT_THAT(EvaluateExpr(*StartsWithExpr(SharedConstant("search"), - SharedConstant(42LL))), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*StartsWithExpr(SharedConstant("search"), + SharedConstant(static_cast(42LL)))), + ReturnsError()); } TEST_F(StartsWithTest, GetEmptyInputsReturnsTrue) { @@ -666,14 +677,16 @@ TEST_F(StartsWithTest, GetLargePrefixReturnsFalse) { // --- StrContains Tests --- TEST_F(StrContainsTest, ValueNonStringIsError) { - EXPECT_THAT(EvaluateExpr(*StrContainsExpr(SharedConstant(42LL), - SharedConstant("value"))), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*StrContainsExpr(SharedConstant(static_cast(42LL)), + SharedConstant("value"))), + ReturnsError()); } TEST_F(StrContainsTest, SubStringNonStringIsError) { - EXPECT_THAT(EvaluateExpr(*StrContainsExpr(SharedConstant("search space"), - SharedConstant(42LL))), + EXPECT_THAT(EvaluateExpr( + *StrContainsExpr(SharedConstant("search space"), + SharedConstant(static_cast(42LL)))), ReturnsError()); } @@ -725,8 +738,9 @@ TEST_F(ToLowerTest, Empty) { } TEST_F(ToLowerTest, NonString) { - EXPECT_THAT(EvaluateExpr(*ToLowerExpr(SharedConstant(123LL))), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*ToLowerExpr(SharedConstant(static_cast(123LL)))), + ReturnsError()); } TEST_F(ToLowerTest, Null) { @@ -746,8 +760,9 @@ TEST_F(ToUpperTest, Empty) { } TEST_F(ToUpperTest, NonString) { - EXPECT_THAT(EvaluateExpr(*ToUpperExpr(SharedConstant(123LL))), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*ToUpperExpr(SharedConstant(static_cast(123LL)))), + ReturnsError()); } TEST_F(ToUpperTest, Null) { @@ -776,7 +791,9 @@ TEST_F(TrimTest, Empty) { } TEST_F(TrimTest, NonString) { - EXPECT_THAT(EvaluateExpr(*TrimExpr(SharedConstant(123LL))), ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*TrimExpr(SharedConstant(static_cast(123LL)))), + ReturnsError()); } TEST_F(TrimTest, Null) { @@ -800,8 +817,9 @@ TEST_F(ReverseTest, Unicode) { } TEST_F(ReverseTest, NonString) { - EXPECT_THAT(EvaluateExpr(*ReverseExpr(SharedConstant(123LL))), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*ReverseExpr(SharedConstant(static_cast(123LL)))), + ReturnsError()); } TEST_F(ReverseTest, Null) { diff --git a/Firestore/core/test/unit/core/expressions/timestamp_test.cc b/Firestore/core/test/unit/core/expressions/timestamp_test.cc index b91dbbff7db..d2fbbaea9f3 100644 --- a/Firestore/core/test/unit/core/expressions/timestamp_test.cc +++ b/Firestore/core/test/unit/core/expressions/timestamp_test.cc @@ -48,20 +48,21 @@ TEST_F(UnixMicrosToTimestampTest, StringTypeReturnsError) { } TEST_F(UnixMicrosToTimestampTest, ZeroValueReturnsTimestampEpoch) { - EXPECT_THAT(EvaluateExpr(*UnixMicrosToTimestampExpr(SharedConstant(0LL))), + EXPECT_THAT(EvaluateExpr(*UnixMicrosToTimestampExpr( + SharedConstant(static_cast(0LL)))), Returns(Value(Timestamp(0, 0)))); } TEST_F(UnixMicrosToTimestampTest, IntTypeReturnsTimestamp) { - EXPECT_THAT( - EvaluateExpr(*UnixMicrosToTimestampExpr(SharedConstant(1000000LL))), - Returns(Value(Timestamp(1, 0)))); + EXPECT_THAT(EvaluateExpr(*UnixMicrosToTimestampExpr( + SharedConstant(static_cast(1000000LL)))), + Returns(Value(Timestamp(1, 0)))); } TEST_F(UnixMicrosToTimestampTest, LongTypeReturnsTimestamp) { - EXPECT_THAT( - EvaluateExpr(*UnixMicrosToTimestampExpr(SharedConstant(9876543210LL))), - Returns(Value(Timestamp(9876, 543210000)))); + EXPECT_THAT(EvaluateExpr(*UnixMicrosToTimestampExpr( + SharedConstant(static_cast(9876543210LL)))), + Returns(Value(Timestamp(9876, 543210000)))); } TEST_F(UnixMicrosToTimestampTest, LongTypeNegativeReturnsTimestamp) { @@ -70,9 +71,9 @@ TEST_F(UnixMicrosToTimestampTest, LongTypeNegativeReturnsTimestamp) { timestamp.which_value_type = google_firestore_v1_Value_timestamp_value_tag; timestamp.timestamp_value.seconds = -1; timestamp.timestamp_value.nanos = 990000000; - EXPECT_THAT( - EvaluateExpr(*UnixMicrosToTimestampExpr(SharedConstant(-10000LL))), - Returns(nanopb::MakeMessage(timestamp))); + EXPECT_THAT(EvaluateExpr(*UnixMicrosToTimestampExpr( + SharedConstant(static_cast(-10000LL)))), + Returns(nanopb::MakeMessage(timestamp))); } TEST_F(UnixMicrosToTimestampTest, LongTypeNegativeOverflowReturnsError) { @@ -86,8 +87,8 @@ TEST_F(UnixMicrosToTimestampTest, LongTypeNegativeOverflowReturnsError) { Returns(Value(Timestamp(-62135596800LL, 0)))); // Test value just below the boundary (using subtraction) - auto below_min_expr = - SubtractExpr({SharedConstant(min_micros), SharedConstant(1LL)}); + auto below_min_expr = SubtractExpr( + {SharedConstant(min_micros), SharedConstant(static_cast(1LL))}); EXPECT_THAT( EvaluateExpr(*UnixMicrosToTimestampExpr(std::move(below_min_expr))), testutil::ReturnsError()); // Fully qualify @@ -123,25 +124,27 @@ TEST_F(UnixMillisToTimestampTest, StringTypeReturnsError) { } TEST_F(UnixMillisToTimestampTest, ZeroValueReturnsTimestampEpoch) { - EXPECT_THAT(EvaluateExpr(*UnixMillisToTimestampExpr(SharedConstant(0LL))), + EXPECT_THAT(EvaluateExpr(*UnixMillisToTimestampExpr( + SharedConstant(static_cast(0LL)))), Returns(Value(Timestamp(0, 0)))); } TEST_F(UnixMillisToTimestampTest, IntTypeReturnsTimestamp) { - EXPECT_THAT(EvaluateExpr(*UnixMillisToTimestampExpr(SharedConstant(1000LL))), + EXPECT_THAT(EvaluateExpr(*UnixMillisToTimestampExpr( + SharedConstant(static_cast(1000LL)))), Returns(Value(Timestamp(1, 0)))); } TEST_F(UnixMillisToTimestampTest, LongTypeReturnsTimestamp) { - EXPECT_THAT( - EvaluateExpr(*UnixMillisToTimestampExpr(SharedConstant(9876543210LL))), - Returns(Value(Timestamp(9876543, 210000000)))); + EXPECT_THAT(EvaluateExpr(*UnixMillisToTimestampExpr( + SharedConstant(static_cast(9876543210LL)))), + Returns(Value(Timestamp(9876543, 210000000)))); } TEST_F(UnixMillisToTimestampTest, LongTypeNegativeReturnsTimestamp) { - EXPECT_THAT( - EvaluateExpr(*UnixMillisToTimestampExpr(SharedConstant(-10000LL))), - Returns(Value(Timestamp(-10, 0)))); + EXPECT_THAT(EvaluateExpr(*UnixMillisToTimestampExpr( + SharedConstant(static_cast(-10000LL)))), + Returns(Value(Timestamp(-10, 0)))); } TEST_F(UnixMillisToTimestampTest, LongTypeNegativeOverflowReturnsError) { @@ -187,25 +190,27 @@ TEST_F(UnixSecondsToTimestampTest, StringTypeReturnsError) { } TEST_F(UnixSecondsToTimestampTest, ZeroValueReturnsTimestampEpoch) { - EXPECT_THAT(EvaluateExpr(*UnixSecondsToTimestampExpr(SharedConstant(0LL))), + EXPECT_THAT(EvaluateExpr(*UnixSecondsToTimestampExpr( + SharedConstant(static_cast(0LL)))), Returns(Value(Timestamp(0, 0)))); } TEST_F(UnixSecondsToTimestampTest, IntTypeReturnsTimestamp) { - EXPECT_THAT(EvaluateExpr(*UnixSecondsToTimestampExpr(SharedConstant(1LL))), + EXPECT_THAT(EvaluateExpr(*UnixSecondsToTimestampExpr( + SharedConstant(static_cast(1LL)))), Returns(Value(Timestamp(1, 0)))); } TEST_F(UnixSecondsToTimestampTest, LongTypeReturnsTimestamp) { - EXPECT_THAT( - EvaluateExpr(*UnixSecondsToTimestampExpr(SharedConstant(9876543210LL))), - Returns(Value(Timestamp(9876543210LL, 0)))); + EXPECT_THAT(EvaluateExpr(*UnixSecondsToTimestampExpr( + SharedConstant(static_cast(9876543210LL)))), + Returns(Value(Timestamp(9876543210LL, 0)))); } TEST_F(UnixSecondsToTimestampTest, LongTypeNegativeReturnsTimestamp) { - EXPECT_THAT( - EvaluateExpr(*UnixSecondsToTimestampExpr(SharedConstant(-10000LL))), - Returns(Value(Timestamp(-10000LL, 0)))); + EXPECT_THAT(EvaluateExpr(*UnixSecondsToTimestampExpr( + SharedConstant(static_cast(-10000LL)))), + Returns(Value(Timestamp(-10000LL, 0)))); } TEST_F(UnixSecondsToTimestampTest, LongTypeNegativeOverflowReturnsError) { @@ -244,7 +249,8 @@ class TimestampToUnixMicrosTest : public TimestampExpressionsTest {}; using testutil::TimestampToUnixMicrosExpr; // Add using declaration TEST_F(TimestampToUnixMicrosTest, NonTimestampTypeReturnsError) { - EXPECT_THAT(EvaluateExpr(*TimestampToUnixMicrosExpr(SharedConstant(123LL))), + EXPECT_THAT(EvaluateExpr(*TimestampToUnixMicrosExpr( + SharedConstant(static_cast(123LL)))), testutil::ReturnsError()); } @@ -324,7 +330,8 @@ class TimestampToUnixMillisTest : public TimestampExpressionsTest {}; using testutil::TimestampToUnixMillisExpr; // Add using declaration TEST_F(TimestampToUnixMillisTest, NonTimestampTypeReturnsError) { - EXPECT_THAT(EvaluateExpr(*TimestampToUnixMillisExpr(SharedConstant(123LL))), + EXPECT_THAT(EvaluateExpr(*TimestampToUnixMillisExpr( + SharedConstant(static_cast(123LL)))), testutil::ReturnsError()); } @@ -397,7 +404,8 @@ class TimestampToUnixSecondsTest : public TimestampExpressionsTest {}; using testutil::TimestampToUnixSecondsExpr; // Add using declaration TEST_F(TimestampToUnixSecondsTest, NonTimestampTypeReturnsError) { - EXPECT_THAT(EvaluateExpr(*TimestampToUnixSecondsExpr(SharedConstant(123LL))), + EXPECT_THAT(EvaluateExpr(*TimestampToUnixSecondsExpr( + SharedConstant(static_cast(123LL)))), testutil::ReturnsError()); } @@ -475,55 +483,55 @@ using testutil::ReturnsNull; // Add using declaration for null checks using testutil::TimestampAddExpr; // Add using declaration TEST_F(TimestampAddTest, TimestampAddStringTypeReturnsError) { - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant("abc"), - SharedConstant("second"), - SharedConstant(1LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant("abc"), SharedConstant("second"), + SharedConstant(static_cast(1LL)))), testutil::ReturnsError()); } TEST_F(TimestampAddTest, TimestampAddZeroValueReturnsTimestampEpoch) { Timestamp epoch(0, 0); - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(epoch), - SharedConstant("second"), - SharedConstant(0LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(epoch), SharedConstant("second"), + SharedConstant(static_cast(0LL)))), Returns(Value(epoch))); } TEST_F(TimestampAddTest, TimestampAddIntTypeReturnsTimestamp) { Timestamp epoch(0, 0); - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(epoch), - SharedConstant("second"), - SharedConstant(1LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(epoch), SharedConstant("second"), + SharedConstant(static_cast(1LL)))), Returns(Value(Timestamp(1, 0)))); } TEST_F(TimestampAddTest, TimestampAddLongTypeReturnsTimestamp) { Timestamp epoch(0, 0); - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(epoch), - SharedConstant("second"), - SharedConstant(9876543210LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(epoch), SharedConstant("second"), + SharedConstant(static_cast(9876543210LL)))), Returns(Value(Timestamp(9876543210LL, 0)))); } TEST_F(TimestampAddTest, TimestampAddLongTypeNegativeReturnsTimestamp) { Timestamp epoch(0, 0); - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(epoch), - SharedConstant("second"), - SharedConstant(-10000LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(epoch), SharedConstant("second"), + SharedConstant(static_cast(-10000LL)))), Returns(Value(Timestamp(-10000LL, 0)))); } TEST_F(TimestampAddTest, TimestampAddLongTypeNegativeOverflowReturnsError) { Timestamp min_ts(-62135596800LL, 0); // Test adding 0 (boundary) - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(min_ts), - SharedConstant("second"), - SharedConstant(0LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(min_ts), SharedConstant("second"), + SharedConstant(static_cast(0LL)))), Returns(Value(min_ts))); // Test adding -1 (overflow) - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(min_ts), - SharedConstant("second"), - SharedConstant(-1LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(min_ts), SharedConstant("second"), + SharedConstant(static_cast(-1LL)))), testutil::ReturnsError()); } @@ -533,73 +541,73 @@ TEST_F(TimestampAddTest, TimestampAddLongTypePositiveOverflowReturnsError) { EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( SharedConstant(max_ts), SharedConstant("microsecond"), // Smallest unit - SharedConstant(0LL))), + SharedConstant(static_cast(0LL)))), Returns(Value(max_ts))); // Expect the same max timestamp // Test adding 1 microsecond (should overflow) - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(max_ts), - SharedConstant("microsecond"), - SharedConstant(1LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(max_ts), SharedConstant("microsecond"), + SharedConstant(static_cast(1LL)))), testutil::ReturnsError()); // Test adding 1 second to a timestamp close to max Timestamp near_max_ts(253402300799LL, 0); - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(near_max_ts), - SharedConstant("second"), - SharedConstant(0LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(near_max_ts), SharedConstant("second"), + SharedConstant(static_cast(0LL)))), Returns(Value(near_max_ts))); - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(near_max_ts), - SharedConstant("second"), - SharedConstant(1LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(near_max_ts), SharedConstant("second"), + SharedConstant(static_cast(1LL)))), testutil::ReturnsError()); } TEST_F(TimestampAddTest, TimestampAddLongTypeMinuteReturnsTimestamp) { Timestamp epoch(0, 0); - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(epoch), - SharedConstant("minute"), - SharedConstant(1LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(epoch), SharedConstant("minute"), + SharedConstant(static_cast(1LL)))), Returns(Value(Timestamp(60, 0)))); } TEST_F(TimestampAddTest, TimestampAddLongTypeHourReturnsTimestamp) { Timestamp epoch(0, 0); - EXPECT_THAT( - EvaluateExpr(*TimestampAddExpr( - SharedConstant(epoch), SharedConstant("hour"), SharedConstant(1LL))), - Returns(Value(Timestamp(3600, 0)))); + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(epoch), SharedConstant("hour"), + SharedConstant(static_cast(1LL)))), + Returns(Value(Timestamp(3600, 0)))); } TEST_F(TimestampAddTest, TimestampAddLongTypeDayReturnsTimestamp) { Timestamp epoch(0, 0); - EXPECT_THAT( - EvaluateExpr(*TimestampAddExpr( - SharedConstant(epoch), SharedConstant("day"), SharedConstant(1LL))), - Returns(Value(Timestamp(86400, 0)))); + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(epoch), SharedConstant("day"), + SharedConstant(static_cast(1LL)))), + Returns(Value(Timestamp(86400, 0)))); } TEST_F(TimestampAddTest, TimestampAddLongTypeMillisecondReturnsTimestamp) { Timestamp epoch(0, 0); - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(epoch), - SharedConstant("millisecond"), - SharedConstant(1LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(epoch), SharedConstant("millisecond"), + SharedConstant(static_cast(1LL)))), Returns(Value(Timestamp(0, 1000000)))); } TEST_F(TimestampAddTest, TimestampAddLongTypeMicrosecondReturnsTimestamp) { Timestamp epoch(0, 0); - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(epoch), - SharedConstant("microsecond"), - SharedConstant(1LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(epoch), SharedConstant("microsecond"), + SharedConstant(static_cast(1LL)))), Returns(Value(Timestamp(0, 1000)))); } TEST_F(TimestampAddTest, TimestampAddInvalidTimeUnitReturnsError) { Timestamp epoch(0, 0); - EXPECT_THAT( - EvaluateExpr(*TimestampAddExpr( - SharedConstant(epoch), SharedConstant("abc"), SharedConstant(1LL))), - testutil::ReturnsError()); + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(epoch), SharedConstant("abc"), + SharedConstant(static_cast(1LL)))), + testutil::ReturnsError()); } TEST_F(TimestampAddTest, TimestampAddInvalidAmountReturnsError) { @@ -620,16 +628,16 @@ TEST_F(TimestampAddTest, TimestampAddNullAmountReturnsNull) { TEST_F(TimestampAddTest, TimestampAddNullTimeUnitReturnsNull) { Timestamp epoch(0, 0); - EXPECT_THAT( - EvaluateExpr(*TimestampAddExpr( - SharedConstant(epoch), SharedConstant(nullptr), SharedConstant(1LL))), - ReturnsNull()); + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(epoch), SharedConstant(nullptr), + SharedConstant(static_cast(1LL)))), + ReturnsNull()); } TEST_F(TimestampAddTest, TimestampAddNullTimestampReturnsNull) { - EXPECT_THAT(EvaluateExpr(*TimestampAddExpr(SharedConstant(nullptr), - SharedConstant("second"), - SharedConstant(1LL))), + EXPECT_THAT(EvaluateExpr(*TimestampAddExpr( + SharedConstant(nullptr), SharedConstant("second"), + SharedConstant(static_cast(1LL)))), ReturnsNull()); } diff --git a/Firestore/core/test/unit/core/pipeline/collection_group_test.cc b/Firestore/core/test/unit/core/pipeline/collection_group_test.cc index c3e1c21eb71..4f12261a038 100644 --- a/Firestore/core/test/unit/core/pipeline/collection_group_test.cc +++ b/Firestore/core/test/unit/core/pipeline/collection_group_test.cc @@ -229,8 +229,8 @@ TEST_F(CollectionGroupTest, WhereOnValues) { TEST_F(CollectionGroupTest, WhereInequalityOnValues) { RealtimePipeline pipeline = StartPipeline("users"); - auto where_expr = - GtExpr({std::make_shared("score"), SharedConstant(80LL)}); + auto where_expr = GtExpr({std::make_shared("score"), + SharedConstant(static_cast(80LL))}); pipeline = pipeline.AddingStage(std::make_shared(where_expr)); auto doc1 = Doc("users/bob", 1000, Map("score", 90LL)); @@ -249,8 +249,8 @@ TEST_F(CollectionGroupTest, WhereInequalityOnValues) { TEST_F(CollectionGroupTest, WhereNotEqualOnValues) { RealtimePipeline pipeline = StartPipeline("users"); - auto where_expr = - NeqExpr({std::make_shared("score"), SharedConstant(50LL)}); + auto where_expr = NeqExpr({std::make_shared("score"), + SharedConstant(static_cast(50LL))}); pipeline = pipeline.AddingStage(std::make_shared(where_expr)); auto doc1 = Doc("users/bob", 1000, Map("score", 90LL)); diff --git a/Firestore/core/test/unit/core/pipeline/collection_test.cc b/Firestore/core/test/unit/core/pipeline/collection_test.cc index 5e02ad433e9..b5962732de1 100644 --- a/Firestore/core/test/unit/core/pipeline/collection_test.cc +++ b/Firestore/core/test/unit/core/pipeline/collection_test.cc @@ -223,8 +223,8 @@ TEST_F(CollectionTest, WhereOnValues) { TEST_F(CollectionTest, WhereInequalityOnValues) { RealtimePipeline pipeline = StartPipeline("/users"); // Use RealtimePipeline - auto where_expr = - GtExpr({std::make_shared("score"), SharedConstant(80LL)}); + auto where_expr = GtExpr({std::make_shared("score"), + SharedConstant(static_cast(80LL))}); pipeline = pipeline.AddingStage(std::make_shared(where_expr)); auto doc1 = Doc("users/bob", 1000, Map("score", 90LL)); @@ -238,8 +238,8 @@ TEST_F(CollectionTest, WhereInequalityOnValues) { TEST_F(CollectionTest, WhereNotEqualOnValues) { RealtimePipeline pipeline = StartPipeline("/users"); // Use RealtimePipeline - auto where_expr = - NeqExpr({std::make_shared("score"), SharedConstant(50LL)}); + auto where_expr = NeqExpr({std::make_shared("score"), + SharedConstant(static_cast(50LL))}); pipeline = pipeline.AddingStage(std::make_shared(where_expr)); auto doc1 = Doc("users/bob", 1000, Map("score", 90LL)); diff --git a/Firestore/core/test/unit/core/pipeline/complex_test.cc b/Firestore/core/test/unit/core/pipeline/complex_test.cc index 9fa651a96dd..abfe8b23d51 100644 --- a/Firestore/core/test/unit/core/pipeline/complex_test.cc +++ b/Firestore/core/test/unit/core/pipeline/complex_test.cc @@ -129,7 +129,8 @@ TEST_F(ComplexPipelineTest, WhereWithMaxNumberOfStages) { for (int i = 1; i <= num_of_fields; ++i) { std::string field_name = "field_" + std::to_string(i); pipeline = pipeline.AddingStage(std::make_shared( - GtExpr({std::make_shared(field_name), SharedConstant(0LL)}))); + GtExpr({std::make_shared(field_name), + SharedConstant(static_cast(0LL))}))); } EXPECT_THAT(RunPipeline(pipeline, documents), @@ -382,14 +383,15 @@ TEST_F(ComplexPipelineTest, WhereWithNestedAddFunctionMaxDepth) { []() { return Value(0LL); }); std::shared_ptr add_func = - AddExpr({std::make_shared("field_1"), SharedConstant(1LL)}); + AddExpr({std::make_shared("field_1"), + SharedConstant(static_cast(1LL))}); for (int i = 1; i < depth; ++i) { - add_func = AddExpr({add_func, SharedConstant(1LL)}); + add_func = AddExpr({add_func, SharedConstant(static_cast(1LL))}); } RealtimePipeline pipeline = StartPipeline("/" + COLLECTION_ID); - pipeline = pipeline.AddingStage( - std::make_shared(GtExpr({add_func, SharedConstant(0LL)}))); + pipeline = pipeline.AddingStage(std::make_shared( + GtExpr({add_func, SharedConstant(static_cast(0LL))}))); // Since field_1 starts at 0, adding 1 repeatedly will always result in > 0 EXPECT_THAT(RunPipeline(pipeline, documents), @@ -437,7 +439,8 @@ TEST_F(ComplexPipelineTest, WhereWithLargeNumberOfConjunctions) { for (int i = 1; i <= num_of_fields; ++i) { std::string field_name = "field_" + std::to_string(i); and_conditions1.push_back( - GtExpr({std::make_shared(field_name), SharedConstant(0LL)})); + GtExpr({std::make_shared(field_name), + SharedConstant(static_cast(0LL))})); // Use LtExpr and a large number for the second condition and_conditions2.push_back( LtExpr({std::make_shared(field_name), diff --git a/Firestore/core/test/unit/testutil/expression_test_util.cc b/Firestore/core/test/unit/testutil/expression_test_util.cc index 0c90fa449ad..965b8927d02 100644 --- a/Firestore/core/test/unit/testutil/expression_test_util.cc +++ b/Firestore/core/test/unit/testutil/expression_test_util.cc @@ -44,7 +44,7 @@ const std::vector> SharedConstant(-std::numeric_limits::max()), SharedConstant(std::numeric_limits::min()), SharedConstant(-kMaxLongExactlyRepresentableAsDouble), - SharedConstant(-1LL), + SharedConstant(static_cast(-1LL)), SharedConstant(-0.5), SharedConstant(-std::numeric_limits::min()), // -MIN_NORMAL SharedConstant( @@ -57,8 +57,8 @@ const std::vector> // (denormalized) SharedConstant(std::numeric_limits::min()), // MIN_NORMAL SharedConstant(0.5), - SharedConstant(1LL), - SharedConstant(42LL), + SharedConstant(static_cast(1LL)), + SharedConstant(static_cast(42LL)), SharedConstant(kMaxLongExactlyRepresentableAsDouble), SharedConstant(std::numeric_limits::max()), SharedConstant(std::numeric_limits::max()), @@ -109,8 +109,9 @@ const std::vector> ComparisonValueTestData::GEO_VALUES = { const std::vector> ComparisonValueTestData::ARRAY_VALUES = {SharedConstant(Array()), - SharedConstant(Array(true, 15LL)), - SharedConstant(Array(1LL, 2LL)), + SharedConstant(Array(true, static_cast(15LL))), + SharedConstant( + Array(static_cast(1LL), static_cast(2LL))), SharedConstant(Array(Value(Timestamp(12, 0)))), SharedConstant(Array("foo")), SharedConstant(Array("foo", "bar")), From 770a72836275e7420fac72a8bcc96fd1fb3fdf6e Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 12 Nov 2025 14:10:20 -0500 Subject: [PATCH 08/36] fix more type error --- .../test/unit/core/expressions/arithmetic_test.cc | 11 ++++++----- .../core/test/unit/testutil/expression_test_util.cc | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Firestore/core/test/unit/core/expressions/arithmetic_test.cc b/Firestore/core/test/unit/core/expressions/arithmetic_test.cc index bf338cb3547..9e9d6c8f606 100644 --- a/Firestore/core/test/unit/core/expressions/arithmetic_test.cc +++ b/Firestore/core/test/unit/core/expressions/arithmetic_test.cc @@ -647,8 +647,8 @@ TEST_F(DivideFunctionTest, PositiveInfinityNegativeInfinityReturnsNan) { TEST_F(ModFunctionTest, DivisorZeroThrowsError) { EXPECT_THAT( - EvaluateExpr(*ModExpr( - {SharedConstant(42LL), SharedConstant(static_cast(0LL))})), + EvaluateExpr(*ModExpr({SharedConstant(static_cast(42LL)), + SharedConstant(static_cast(0LL))})), ReturnsError()); // Note: C++ doesn't distinguish -0LL from 0LL // EXPECT_TRUE(AssertResultEquals( @@ -665,9 +665,10 @@ TEST_F(ModFunctionTest, DivisorZeroThrowsError) { } TEST_F(ModFunctionTest, DividendZeroReturnsZero) { - EXPECT_THAT(EvaluateExpr(*ModExpr({SharedConstant(static_cast(0LL)), - SharedConstant(42LL)})), - Returns(Value(0LL))); + EXPECT_THAT( + EvaluateExpr(*ModExpr({SharedConstant(static_cast(0LL)), + SharedConstant(static_cast(42LL))})), + Returns(Value(0LL))); // Note: C++ doesn't distinguish -0LL from 0LL // EXPECT_THAT( // EvaluateExpr(*ModExpr({SharedConstant(-0LL), SharedConstant(42LL)})), diff --git a/Firestore/core/test/unit/testutil/expression_test_util.cc b/Firestore/core/test/unit/testutil/expression_test_util.cc index 965b8927d02..a2b19e2e354 100644 --- a/Firestore/core/test/unit/testutil/expression_test_util.cc +++ b/Firestore/core/test/unit/testutil/expression_test_util.cc @@ -81,7 +81,7 @@ const std::vector> // C++ SharedConstant("santé"), SharedConstant("santé et bonheur")}; -const auto ComparisonValueTestData::BYTE_VALUES = +const std::vector> ComparisonValueTestData::BYTE_VALUES = std::vector>{ SharedConstant(*BlobValue()), // Empty - use default constructor SharedConstant(*BlobValue(0, 2, 56, 42)), // Use variadic args From 559a35599eb6519a58d791424c71c7e2c2337313 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 12 Nov 2025 18:41:57 -0500 Subject: [PATCH 09/36] try solving assertion failure --- .../empty_credentials_provider_test.cc | 5 ++++ Firestore/core/test/unit/timestamp_test.cc | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/Firestore/core/test/unit/credentials/empty_credentials_provider_test.cc b/Firestore/core/test/unit/credentials/empty_credentials_provider_test.cc index 8affd58f34c..b625a7eecb4 100644 --- a/Firestore/core/test/unit/credentials/empty_credentials_provider_test.cc +++ b/Firestore/core/test/unit/credentials/empty_credentials_provider_test.cc @@ -18,6 +18,7 @@ #include "Firestore/core/src/credentials/credentials_fwd.h" #include "Firestore/core/src/util/statusor.h" +#include "gtest/gtest-death-test.h" #include "gtest/gtest.h" namespace firebase { @@ -29,7 +30,11 @@ TEST(EmptyAuthCredentialsProvider, GetToken) { credentials_provider.GetToken([](util::StatusOr result) { EXPECT_TRUE(result.ok()); const AuthToken& token = result.ValueOrDie(); +#if DEBUG + EXPECT_DEATH(token.token(), "user_.is_authenticated()"); +#else EXPECT_ANY_THROW(token.token()); +#endif const User& user = token.user(); EXPECT_EQ("", user.uid()); EXPECT_FALSE(user.is_authenticated()); diff --git a/Firestore/core/test/unit/timestamp_test.cc b/Firestore/core/test/unit/timestamp_test.cc index b9d4e9c40dd..ac91f3444cc 100644 --- a/Firestore/core/test/unit/timestamp_test.cc +++ b/Firestore/core/test/unit/timestamp_test.cc @@ -22,6 +22,7 @@ #include #include "Firestore/core/src/util/warnings.h" +#include "gtest/gtest-death-test.h" #include "gtest/gtest.h" SUPPRESS_COMMA_WARNINGS_BEGIN() @@ -275,6 +276,19 @@ TEST(Timestamp, Comparison) { } TEST(Timestamp, InvalidArguments) { +#if DEBUG + // Negative nanoseconds. + ASSERT_DEATH(Timestamp(0, -1), "nanoseconds"); + ASSERT_DEATH(Timestamp(100, -1), "nanoseconds"); + ASSERT_DEATH(Timestamp(100, -12346789), "nanoseconds"); + + // Nanoseconds that are more than one second. + ASSERT_DEATH(Timestamp(0, 999999999 + 1), "nanoseconds"); + + // Seconds beyond supported range. + ASSERT_DEATH(Timestamp(kLowerBound - 1, 0), "seconds"); + ASSERT_DEATH(Timestamp(kUpperBound + 1, 0), "seconds"); +#else // Negative nanoseconds. ASSERT_ANY_THROW(Timestamp(0, -1)); ASSERT_ANY_THROW(Timestamp(100, -1)); @@ -286,18 +300,30 @@ TEST(Timestamp, InvalidArguments) { // Seconds beyond supported range. ASSERT_ANY_THROW(Timestamp(kLowerBound - 1, 0)); ASSERT_ANY_THROW(Timestamp(kUpperBound + 1, 0)); +#endif } TEST(Timestamp, InvalidArgumentsChrono) { // Make sure Timestamp doesn't accept values beyond the supported range, if // system clock-based time_point on this platform can represent values this // large. +#if DEBUG + if (CanSystemClockDurationHold(Sec(kUpperBound + 1))) { + ASSERT_DEATH(Timestamp::FromTimePoint(TimePoint{Sec(kUpperBound + 1)}), + "seconds"); + } + if (CanSystemClockDurationHold(Sec(kLowerBound - 1))) { + ASSERT_DEATH(Timestamp::FromTimePoint(TimePoint{Sec(kLowerBound - 1)}), + "seconds"); + } +#else if (CanSystemClockDurationHold(Sec(kUpperBound + 1))) { ASSERT_ANY_THROW(Timestamp::FromTimePoint(TimePoint{Sec(kUpperBound + 1)})); } if (CanSystemClockDurationHold(Sec(kLowerBound - 1))) { ASSERT_ANY_THROW(Timestamp::FromTimePoint(TimePoint{Sec(kLowerBound - 1)})); } +#endif } TEST(Timestamp, ToString) { From 9035aad89f66ea8abe938c851b309a6fd700e593 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Thu, 13 Nov 2025 10:06:35 -0500 Subject: [PATCH 10/36] try another flag --- Firestore/core/test/unit/timestamp_test.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firestore/core/test/unit/timestamp_test.cc b/Firestore/core/test/unit/timestamp_test.cc index ac91f3444cc..cc21897c270 100644 --- a/Firestore/core/test/unit/timestamp_test.cc +++ b/Firestore/core/test/unit/timestamp_test.cc @@ -276,7 +276,7 @@ TEST(Timestamp, Comparison) { } TEST(Timestamp, InvalidArguments) { -#if DEBUG +#if !defined(NDEBUG) // Negative nanoseconds. ASSERT_DEATH(Timestamp(0, -1), "nanoseconds"); ASSERT_DEATH(Timestamp(100, -1), "nanoseconds"); @@ -307,7 +307,7 @@ TEST(Timestamp, InvalidArgumentsChrono) { // Make sure Timestamp doesn't accept values beyond the supported range, if // system clock-based time_point on this platform can represent values this // large. -#if DEBUG +#if !defined(NDEBUG) if (CanSystemClockDurationHold(Sec(kUpperBound + 1))) { ASSERT_DEATH(Timestamp::FromTimePoint(TimePoint{Sec(kUpperBound + 1)}), "seconds"); From e0fe92dc49c7abc96ed84ccc293e8b552355665e Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Thu, 13 Nov 2025 10:17:34 -0500 Subject: [PATCH 11/36] test ASSERT_DEATH on github ci --- Firestore/core/test/unit/timestamp_test.cc | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Firestore/core/test/unit/timestamp_test.cc b/Firestore/core/test/unit/timestamp_test.cc index cc21897c270..5897d2965e6 100644 --- a/Firestore/core/test/unit/timestamp_test.cc +++ b/Firestore/core/test/unit/timestamp_test.cc @@ -307,7 +307,6 @@ TEST(Timestamp, InvalidArgumentsChrono) { // Make sure Timestamp doesn't accept values beyond the supported range, if // system clock-based time_point on this platform can represent values this // large. -#if !defined(NDEBUG) if (CanSystemClockDurationHold(Sec(kUpperBound + 1))) { ASSERT_DEATH(Timestamp::FromTimePoint(TimePoint{Sec(kUpperBound + 1)}), "seconds"); @@ -316,14 +315,6 @@ TEST(Timestamp, InvalidArgumentsChrono) { ASSERT_DEATH(Timestamp::FromTimePoint(TimePoint{Sec(kLowerBound - 1)}), "seconds"); } -#else - if (CanSystemClockDurationHold(Sec(kUpperBound + 1))) { - ASSERT_ANY_THROW(Timestamp::FromTimePoint(TimePoint{Sec(kUpperBound + 1)})); - } - if (CanSystemClockDurationHold(Sec(kLowerBound - 1))) { - ASSERT_ANY_THROW(Timestamp::FromTimePoint(TimePoint{Sec(kLowerBound - 1)})); - } -#endif } TEST(Timestamp, ToString) { From 8b7df8cc6a445a490334ddaad3e15feae308621a Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Thu, 13 Nov 2025 11:16:13 -0500 Subject: [PATCH 12/36] test new flag: ABSL_HAVE_EXCEPTIONS --- Firestore/core/test/unit/timestamp_test.cc | 25 ++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/Firestore/core/test/unit/timestamp_test.cc b/Firestore/core/test/unit/timestamp_test.cc index 5897d2965e6..3dc6f9d77e8 100644 --- a/Firestore/core/test/unit/timestamp_test.cc +++ b/Firestore/core/test/unit/timestamp_test.cc @@ -308,12 +308,29 @@ TEST(Timestamp, InvalidArgumentsChrono) { // system clock-based time_point on this platform can represent values this // large. if (CanSystemClockDurationHold(Sec(kUpperBound + 1))) { - ASSERT_DEATH(Timestamp::FromTimePoint(TimePoint{Sec(kUpperBound + 1)}), - "seconds"); + auto action = [] { + Timestamp::FromTimePoint(TimePoint{Sec(kUpperBound + 1)}); + }; + +#if ABSL_HAVE_EXCEPTIONS + // Expect a C++ exception to be thrown + ASSERT_ANY_THROW(action()); +#else + // Expect the process to terminate + ASSERT_DEATH(action(), "Timestamp seconds out of range"); +#endif } + if (CanSystemClockDurationHold(Sec(kLowerBound - 1))) { - ASSERT_DEATH(Timestamp::FromTimePoint(TimePoint{Sec(kLowerBound - 1)}), - "seconds"); + auto action = [] { + Timestamp::FromTimePoint(TimePoint{Sec(kLowerBound - 1)}); + }; + +#if ABSL_HAVE_EXCEPTIONS + ASSERT_ANY_THROW(action()); +#else + ASSERT_DEATH(action(), "Timestamp seconds out of range"); +#endif } } From 8cce4af3835adc24d8fe08b5d4f919c4ffd58cf3 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Thu, 13 Nov 2025 22:25:54 -0500 Subject: [PATCH 13/36] verify behaviour --- Firestore/core/test/unit/timestamp_test.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Firestore/core/test/unit/timestamp_test.cc b/Firestore/core/test/unit/timestamp_test.cc index 3dc6f9d77e8..bdd8247c266 100644 --- a/Firestore/core/test/unit/timestamp_test.cc +++ b/Firestore/core/test/unit/timestamp_test.cc @@ -17,6 +17,7 @@ #include "Firestore/core/include/firebase/firestore/timestamp.h" #include +#include #include #include #include @@ -314,9 +315,11 @@ TEST(Timestamp, InvalidArgumentsChrono) { #if ABSL_HAVE_EXCEPTIONS // Expect a C++ exception to be thrown + printf("Testing upper bound with exceptions\n"); ASSERT_ANY_THROW(action()); #else // Expect the process to terminate + printf("Testing upper bound without exceptions\n"); ASSERT_DEATH(action(), "Timestamp seconds out of range"); #endif } @@ -327,8 +330,10 @@ TEST(Timestamp, InvalidArgumentsChrono) { }; #if ABSL_HAVE_EXCEPTIONS + printf("Testing lower bound with exceptions\n"); ASSERT_ANY_THROW(action()); #else + printf("Testing lower bound without exceptions\n"); ASSERT_DEATH(action(), "Timestamp seconds out of range"); #endif } From f83e670a0b212a416de65b928e5413bff0532bc7 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Thu, 13 Nov 2025 23:32:12 -0500 Subject: [PATCH 14/36] test reverted re2 version --- cmake/external/re2.cmake | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmake/external/re2.cmake b/cmake/external/re2.cmake index 50648cec17f..340ff6bd52f 100644 --- a/cmake/external/re2.cmake +++ b/cmake/external/re2.cmake @@ -18,16 +18,16 @@ if(TARGET RE2) return() endif() -# Based on https://github.com/grpc/grpc/blob/v1.69.x/bazel/grpc_deps.bzl -set(version 2022-04-01) +# Based on https://github.com/grpc/grpc/blob/v1.44.0/bazel/grpc_deps.bzl +set(commit 8e08f47b11b413302749c0d8b17a1c94777495d5) ExternalProject_Add( re2 DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} - DOWNLOAD_NAME re2-${version}.tar.gz - URL https://github.com/google/re2/archive/${version}.tar.gz - URL_HASH SHA256=1ae8ccfdb1066a731bba6ee0881baad5efd2cd661acd9569b689f2586e1a50e9 + DOWNLOAD_NAME re2-${commit}.tar.gz + URL https://github.com/google/re2/archive/${commit}.tar.gz + URL_HASH SHA256=319a58a58d8af295db97dfeecc4e250179c5966beaa2d842a82f0a013b6a239b PREFIX ${PROJECT_BINARY_DIR} SOURCE_DIR ${PROJECT_BINARY_DIR}/src/re2 @@ -36,4 +36,4 @@ ExternalProject_Add( BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" -) +) \ No newline at end of file From e2e053dcc2e47958d0210f5bdc3290c59cff670c Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Fri, 14 Nov 2025 10:20:43 -0500 Subject: [PATCH 15/36] add cmake settings --- cmake/external/re2.cmake | 12 ++++++------ scripts/build.sh | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cmake/external/re2.cmake b/cmake/external/re2.cmake index 340ff6bd52f..50648cec17f 100644 --- a/cmake/external/re2.cmake +++ b/cmake/external/re2.cmake @@ -18,16 +18,16 @@ if(TARGET RE2) return() endif() -# Based on https://github.com/grpc/grpc/blob/v1.44.0/bazel/grpc_deps.bzl -set(commit 8e08f47b11b413302749c0d8b17a1c94777495d5) +# Based on https://github.com/grpc/grpc/blob/v1.69.x/bazel/grpc_deps.bzl +set(version 2022-04-01) ExternalProject_Add( re2 DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} - DOWNLOAD_NAME re2-${commit}.tar.gz - URL https://github.com/google/re2/archive/${commit}.tar.gz - URL_HASH SHA256=319a58a58d8af295db97dfeecc4e250179c5966beaa2d842a82f0a013b6a239b + DOWNLOAD_NAME re2-${version}.tar.gz + URL https://github.com/google/re2/archive/${version}.tar.gz + URL_HASH SHA256=1ae8ccfdb1066a731bba6ee0881baad5efd2cd661acd9569b689f2586e1a50e9 PREFIX ${PROJECT_BINARY_DIR} SOURCE_DIR ${PROJECT_BINARY_DIR}/src/re2 @@ -36,4 +36,4 @@ ExternalProject_Add( BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" -) \ No newline at end of file +) diff --git a/scripts/build.sh b/scripts/build.sh index b50583167c9..283dc893e44 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -271,6 +271,7 @@ xcb_flags=("${xcb_flags[@]}" "${buildcache_xcb_flags[@]}") cmake_options=( -Wdeprecated -DCMAKE_BUILD_TYPE=Debug + -DABSL_ENABLE_EXCEPTIONS=1 ) if [[ -n "${SANITIZERS:-}" ]]; then From d462e20830ac778c6287c2f0c2f4e1c602c08455 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Fri, 14 Nov 2025 11:35:16 -0500 Subject: [PATCH 16/36] add absl cmake settings --- cmake/external/abseil-cpp.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmake/external/abseil-cpp.cmake b/cmake/external/abseil-cpp.cmake index 0d8c33ed940..2ebf6a252bd 100644 --- a/cmake/external/abseil-cpp.cmake +++ b/cmake/external/abseil-cpp.cmake @@ -26,6 +26,14 @@ ExternalProject_Add( PREFIX ${PROJECT_BINARY_DIR} + CMAKE_ARGS + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_CXX_STANDARD=11 + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + -DBUILD_TESTING=OFF + -DABSL_PROPAGATE_CXX_STD=ON + -DABSL_ENABLE_EXCEPTIONS=1 + CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From f90bdfe3af473667c6be5eba0167516f353a9a17 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Mon, 17 Nov 2025 10:05:14 -0500 Subject: [PATCH 17/36] revert changes --- Firestore/core/test/unit/timestamp_test.cc | 45 +--------------------- cmake/external/abseil-cpp.cmake | 8 ---- scripts/build.sh | 1 - 3 files changed, 2 insertions(+), 52 deletions(-) diff --git a/Firestore/core/test/unit/timestamp_test.cc b/Firestore/core/test/unit/timestamp_test.cc index bdd8247c266..e24b1e87396 100644 --- a/Firestore/core/test/unit/timestamp_test.cc +++ b/Firestore/core/test/unit/timestamp_test.cc @@ -17,13 +17,11 @@ #include "Firestore/core/include/firebase/firestore/timestamp.h" #include -#include #include #include #include #include "Firestore/core/src/util/warnings.h" -#include "gtest/gtest-death-test.h" #include "gtest/gtest.h" SUPPRESS_COMMA_WARNINGS_BEGIN() @@ -277,31 +275,15 @@ TEST(Timestamp, Comparison) { } TEST(Timestamp, InvalidArguments) { -#if !defined(NDEBUG) - // Negative nanoseconds. - ASSERT_DEATH(Timestamp(0, -1), "nanoseconds"); - ASSERT_DEATH(Timestamp(100, -1), "nanoseconds"); - ASSERT_DEATH(Timestamp(100, -12346789), "nanoseconds"); - - // Nanoseconds that are more than one second. - ASSERT_DEATH(Timestamp(0, 999999999 + 1), "nanoseconds"); - - // Seconds beyond supported range. - ASSERT_DEATH(Timestamp(kLowerBound - 1, 0), "seconds"); - ASSERT_DEATH(Timestamp(kUpperBound + 1, 0), "seconds"); -#else // Negative nanoseconds. ASSERT_ANY_THROW(Timestamp(0, -1)); ASSERT_ANY_THROW(Timestamp(100, -1)); ASSERT_ANY_THROW(Timestamp(100, -12346789)); - // Nanoseconds that are more than one second. ASSERT_ANY_THROW(Timestamp(0, 999999999 + 1)); - // Seconds beyond supported range. ASSERT_ANY_THROW(Timestamp(kLowerBound - 1, 0)); ASSERT_ANY_THROW(Timestamp(kUpperBound + 1, 0)); -#endif } TEST(Timestamp, InvalidArgumentsChrono) { @@ -309,33 +291,10 @@ TEST(Timestamp, InvalidArgumentsChrono) { // system clock-based time_point on this platform can represent values this // large. if (CanSystemClockDurationHold(Sec(kUpperBound + 1))) { - auto action = [] { - Timestamp::FromTimePoint(TimePoint{Sec(kUpperBound + 1)}); - }; - -#if ABSL_HAVE_EXCEPTIONS - // Expect a C++ exception to be thrown - printf("Testing upper bound with exceptions\n"); - ASSERT_ANY_THROW(action()); -#else - // Expect the process to terminate - printf("Testing upper bound without exceptions\n"); - ASSERT_DEATH(action(), "Timestamp seconds out of range"); -#endif + ASSERT_ANY_THROW(Timestamp::FromTimePoint(TimePoint{Sec(kUpperBound + 1)})); } - if (CanSystemClockDurationHold(Sec(kLowerBound - 1))) { - auto action = [] { - Timestamp::FromTimePoint(TimePoint{Sec(kLowerBound - 1)}); - }; - -#if ABSL_HAVE_EXCEPTIONS - printf("Testing lower bound with exceptions\n"); - ASSERT_ANY_THROW(action()); -#else - printf("Testing lower bound without exceptions\n"); - ASSERT_DEATH(action(), "Timestamp seconds out of range"); -#endif + ASSERT_ANY_THROW(Timestamp::FromTimePoint(TimePoint{Sec(kLowerBound - 1)})); } } diff --git a/cmake/external/abseil-cpp.cmake b/cmake/external/abseil-cpp.cmake index 2ebf6a252bd..0d8c33ed940 100644 --- a/cmake/external/abseil-cpp.cmake +++ b/cmake/external/abseil-cpp.cmake @@ -26,14 +26,6 @@ ExternalProject_Add( PREFIX ${PROJECT_BINARY_DIR} - CMAKE_ARGS - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DCMAKE_CXX_STANDARD=11 - -DCMAKE_POSITION_INDEPENDENT_CODE=ON - -DBUILD_TESTING=OFF - -DABSL_PROPAGATE_CXX_STD=ON - -DABSL_ENABLE_EXCEPTIONS=1 - CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/scripts/build.sh b/scripts/build.sh index db28386fa90..f9a79ef0960 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -271,7 +271,6 @@ xcb_flags=("${xcb_flags[@]}" "${buildcache_xcb_flags[@]}") cmake_options=( -Wdeprecated -DCMAKE_BUILD_TYPE=Debug - -DABSL_ENABLE_EXCEPTIONS=1 ) if [[ -n "${SANITIZERS:-}" ]]; then From 44195b847505e867dee1e36a1344766eb527972b Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Mon, 17 Nov 2025 10:47:34 -0500 Subject: [PATCH 18/36] fix stack-use-after-scope --- Firestore/core/src/core/expressions_eval.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Firestore/core/src/core/expressions_eval.cc b/Firestore/core/src/core/expressions_eval.cc index 8c2cd3b12ee..cdc8c9bd7f0 100644 --- a/Firestore/core/src/core/expressions_eval.cc +++ b/Firestore/core/src/core/expressions_eval.cc @@ -990,10 +990,9 @@ EvaluateResult CoreTrim::Evaluate( switch (evaluated.type()) { case EvaluateResult::ResultType::kString: { - absl::string_view trimmed_view = absl::StripAsciiWhitespace( - nanopb::MakeString(evaluated.value()->string_value)); - return EvaluateResult::NewValue( - model::StringValue(std::move(trimmed_view))); + std::string str = nanopb::MakeString(evaluated.value()->string_value); + absl::string_view trimmed_view = absl::StripAsciiWhitespace(str); + return EvaluateResult::NewValue(model::StringValue(trimmed_view)); } case EvaluateResult::ResultType::kNull: return EvaluateResult::NewNull(); From 0a30c20b5d56238bf25cd0d9eb3eceaecb3d110d Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Mon, 17 Nov 2025 12:39:27 -0500 Subject: [PATCH 19/36] remove unnessary changes --- .../test/unit/credentials/empty_credentials_provider_test.cc | 5 ----- Firestore/core/test/unit/timestamp_test.cc | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Firestore/core/test/unit/credentials/empty_credentials_provider_test.cc b/Firestore/core/test/unit/credentials/empty_credentials_provider_test.cc index b625a7eecb4..8affd58f34c 100644 --- a/Firestore/core/test/unit/credentials/empty_credentials_provider_test.cc +++ b/Firestore/core/test/unit/credentials/empty_credentials_provider_test.cc @@ -18,7 +18,6 @@ #include "Firestore/core/src/credentials/credentials_fwd.h" #include "Firestore/core/src/util/statusor.h" -#include "gtest/gtest-death-test.h" #include "gtest/gtest.h" namespace firebase { @@ -30,11 +29,7 @@ TEST(EmptyAuthCredentialsProvider, GetToken) { credentials_provider.GetToken([](util::StatusOr result) { EXPECT_TRUE(result.ok()); const AuthToken& token = result.ValueOrDie(); -#if DEBUG - EXPECT_DEATH(token.token(), "user_.is_authenticated()"); -#else EXPECT_ANY_THROW(token.token()); -#endif const User& user = token.user(); EXPECT_EQ("", user.uid()); EXPECT_FALSE(user.is_authenticated()); diff --git a/Firestore/core/test/unit/timestamp_test.cc b/Firestore/core/test/unit/timestamp_test.cc index e24b1e87396..b9d4e9c40dd 100644 --- a/Firestore/core/test/unit/timestamp_test.cc +++ b/Firestore/core/test/unit/timestamp_test.cc @@ -279,8 +279,10 @@ TEST(Timestamp, InvalidArguments) { ASSERT_ANY_THROW(Timestamp(0, -1)); ASSERT_ANY_THROW(Timestamp(100, -1)); ASSERT_ANY_THROW(Timestamp(100, -12346789)); + // Nanoseconds that are more than one second. ASSERT_ANY_THROW(Timestamp(0, 999999999 + 1)); + // Seconds beyond supported range. ASSERT_ANY_THROW(Timestamp(kLowerBound - 1, 0)); ASSERT_ANY_THROW(Timestamp(kUpperBound + 1, 0)); From af72cd8936575fb693a0ba6d3243e3bd7ec0d7a1 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Mon, 17 Nov 2025 13:42:29 -0500 Subject: [PATCH 20/36] enable emulator EXPERIMENTAL_MODE --- scripts/run_firestore_emulator.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/run_firestore_emulator.sh b/scripts/run_firestore_emulator.sh index 7401009c44d..3d1563c2f13 100755 --- a/scripts/run_firestore_emulator.sh +++ b/scripts/run_firestore_emulator.sh @@ -25,7 +25,7 @@ if [[ ! -z "${JAVA_HOME_11_X64:-}" ]]; then export JAVA_HOME=$JAVA_HOME_11_X64 fi -VERSION='1.19.7' +VERSION='1.19.9' FILENAME="cloud-firestore-emulator-v${VERSION}.jar" URL="https://storage.googleapis.com/firebase-preview-drop/emulator/${FILENAME}" @@ -53,7 +53,8 @@ function ensure_exists() { # Runs the emulator synchronously function run() { - exec java -jar "$jar" "$@" + echo "Running command: EXPERIMENTAL_MODE=true java -jar \"$jar\" \"$@\"" + EXPERIMENTAL_MODE=true exec java -jar "$jar" "$@" } # Verifies the emulator isn't already running at the PID in the pid_file From 5721bf9a75df41f008af7b7b8bdb51688c3e3d42 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Tue, 18 Nov 2025 15:38:13 -0500 Subject: [PATCH 21/36] update emulator version --- scripts/run_firestore_emulator.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run_firestore_emulator.sh b/scripts/run_firestore_emulator.sh index 3d1563c2f13..07f7c93cf2b 100755 --- a/scripts/run_firestore_emulator.sh +++ b/scripts/run_firestore_emulator.sh @@ -25,7 +25,7 @@ if [[ ! -z "${JAVA_HOME_11_X64:-}" ]]; then export JAVA_HOME=$JAVA_HOME_11_X64 fi -VERSION='1.19.9' +VERSION='1.20.2' FILENAME="cloud-firestore-emulator-v${VERSION}.jar" URL="https://storage.googleapis.com/firebase-preview-drop/emulator/${FILENAME}" From ac6286e4ad5a7a2be3686d26c6f39024398c85c1 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 19 Nov 2025 10:18:39 -0500 Subject: [PATCH 22/36] remove echo --- scripts/run_firestore_emulator.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/run_firestore_emulator.sh b/scripts/run_firestore_emulator.sh index 07f7c93cf2b..cb3e53c0648 100755 --- a/scripts/run_firestore_emulator.sh +++ b/scripts/run_firestore_emulator.sh @@ -53,7 +53,6 @@ function ensure_exists() { # Runs the emulator synchronously function run() { - echo "Running command: EXPERIMENTAL_MODE=true java -jar \"$jar\" \"$@\"" EXPERIMENTAL_MODE=true exec java -jar "$jar" "$@" } From 454c75eec65d3efc58f6d80b7674bdd70a78a97b Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Fri, 21 Nov 2025 15:15:39 -0500 Subject: [PATCH 23/36] rename some expressions --- Firestore/core/src/core/expressions_eval.cc | 81 +- Firestore/core/src/core/expressions_eval.h | 47 +- Firestore/core/src/core/pipeline_util.cc | 21 +- .../unit/core/expressions/comparison_test.cc | 818 +++++++++--------- .../unit/core/expressions/logical_test.cc | 110 ++- .../expressions/mirroring_semantics_test.cc | 38 +- .../test/unit/core/expressions/string_test.cc | 102 +-- .../unit/core/pipeline/canonify_eq_test.cc | 22 +- .../core/pipeline/collection_group_test.cc | 13 +- .../unit/core/pipeline/collection_test.cc | 13 +- .../test/unit/core/pipeline/complex_test.cc | 30 +- .../unit/core/pipeline/disjunctive_test.cc | 293 ++++--- .../unit/core/pipeline/error_handling_test.cc | 47 +- .../unit/core/pipeline/inequality_test.cc | 224 ++--- .../core/pipeline/nested_properties_test.cc | 84 +- .../unit/core/pipeline/null_semantics_test.cc | 180 ++-- .../core/pipeline/number_semantics_test.cc | 53 +- .../core/test/unit/core/pipeline/sort_test.cc | 20 +- .../test/unit/core/pipeline/unicode_test.cc | 19 +- .../test/unit/core/pipeline/where_test.cc | 102 ++- .../core/test/unit/core/pipeline_util_test.cc | 10 +- .../test/unit/local/local_serializer_test.cc | 8 +- .../core/test/unit/local/query_engine_test.cc | 16 +- .../test/unit/testutil/expression_test_util.h | 61 +- 24 files changed, 1266 insertions(+), 1146 deletions(-) diff --git a/Firestore/core/src/core/expressions_eval.cc b/Firestore/core/src/core/expressions_eval.cc index cdc8c9bd7f0..3b19e1629fd 100644 --- a/Firestore/core/src/core/expressions_eval.cc +++ b/Firestore/core/src/core/expressions_eval.cc @@ -201,8 +201,8 @@ EvaluateResult EvaluateResult::NewValue( std::unique_ptr FunctionToEvaluable( const api::FunctionExpr& function) { - if (function.name() == "eq") { - return std::make_unique(function); + if (function.name() == "equal") { + return std::make_unique(function); } else if (function.name() == "add") { return std::make_unique(function); } else if (function.name() == "subtract") { @@ -213,16 +213,16 @@ std::unique_ptr FunctionToEvaluable( return std::make_unique(function); } else if (function.name() == "mod") { return std::make_unique(function); - } else if (function.name() == "neq") { - return std::make_unique(function); - } else if (function.name() == "lt") { - return std::make_unique(function); - } else if (function.name() == "lte") { - return std::make_unique(function); - } else if (function.name() == "gt") { - return std::make_unique(function); - } else if (function.name() == "gte") { - return std::make_unique(function); + } else if (function.name() == "not_equal") { + return std::make_unique(function); + } else if (function.name() == "less_than") { + return std::make_unique(function); + } else if (function.name() == "less_than_or_equal") { + return std::make_unique(function); + } else if (function.name() == "greater_than") { + return std::make_unique(function); + } else if (function.name() == "greater_than_or_equal") { + return std::make_unique(function); } else if (function.name() == "array_reverse") { // Removed array_concat return std::make_unique(function); } else if (function.name() == "array_contains") { @@ -259,33 +259,32 @@ std::unique_ptr FunctionToEvaluable( return std::make_unique(function); } else if (function.name() == "is_error") { return std::make_unique(function); - } else if (function.name() == "logical_maximum") { - return std::make_unique(function); - } else if (function.name() == "logical_minimum") { - return std::make_unique(function); + } else if (function.name() == "maximum") { + return std::make_unique(function); + } else if (function.name() == "minimum") { + return std::make_unique(function); } else if (function.name() == "map_get") { return std::make_unique(function); } else if (function.name() == "byte_length") { return std::make_unique(function); } else if (function.name() == "char_length") { return std::make_unique(function); - } else if (function.name() == "str_concat") { - return std::make_unique(function); + } else if (function.name() == "string_concat") { + return std::make_unique(function); } else if (function.name() == "ends_with") { return std::make_unique(function); } else if (function.name() == "starts_with") { return std::make_unique(function); - } else if (function.name() == "str_contains") { - return std::make_unique(function); + } else if (function.name() == "string_contains") { + return std::make_unique(function); } else if (function.name() == "to_lower") { return std::make_unique(function); } else if (function.name() == "to_upper") { return std::make_unique(function); } else if (function.name() == "trim") { return std::make_unique(function); - } else if (function.name() == "reverse") { - // Note: This handles string reverse. Array reverse is separate. - return std::make_unique(function); + } else if (function.name() == "string_reverse") { + return std::make_unique(function); } else if (function.name() == "regex_contains") { return std::make_unique(function); } else if (function.name() == "regex_match") { @@ -427,8 +426,8 @@ EvaluateResult ComparisonBase::Evaluate( return CompareToResult(left, right); } -EvaluateResult CoreEq::CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const { +EvaluateResult CoreEqual::CompareToResult(const EvaluateResult& left, + const EvaluateResult& right) const { // Type mismatch always results in false for Eq if (model::GetTypeOrder(*left.value()) != model::GetTypeOrder(*right.value())) { @@ -450,8 +449,8 @@ EvaluateResult CoreEq::CompareToResult(const EvaluateResult& left, HARD_FAIL("Unhandled case in switch statement"); } -EvaluateResult CoreNeq::CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const { +EvaluateResult CoreNotEqual::CompareToResult( + const EvaluateResult& left, const EvaluateResult& right) const { // NaN != anything (including NaN) is true if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); @@ -473,8 +472,8 @@ EvaluateResult CoreNeq::CompareToResult(const EvaluateResult& left, HARD_FAIL("Unhandled case in switch statement"); } -EvaluateResult CoreLt::CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const { +EvaluateResult CoreLessThan::CompareToResult( + const EvaluateResult& left, const EvaluateResult& right) const { // Type mismatch always results in false if (model::GetTypeOrder(*left.value()) != model::GetTypeOrder(*right.value())) { @@ -491,8 +490,8 @@ EvaluateResult CoreLt::CompareToResult(const EvaluateResult& left, nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); } -EvaluateResult CoreLte::CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const { +EvaluateResult CoreLessThanOrEqual::CompareToResult( + const EvaluateResult& left, const EvaluateResult& right) const { // Type mismatch always results in false if (model::GetTypeOrder(*left.value()) != model::GetTypeOrder(*right.value())) { @@ -516,8 +515,8 @@ EvaluateResult CoreLte::CompareToResult(const EvaluateResult& left, nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); } -EvaluateResult CoreGt::CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const { +EvaluateResult CoreGreaterThan::CompareToResult( + const EvaluateResult& left, const EvaluateResult& right) const { // Type mismatch always results in false if (model::GetTypeOrder(*left.value()) != model::GetTypeOrder(*right.value())) { @@ -534,8 +533,8 @@ EvaluateResult CoreGt::CompareToResult(const EvaluateResult& left, nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); } -EvaluateResult CoreGte::CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const { +EvaluateResult CoreGreaterThanOrEqual::CompareToResult( + const EvaluateResult& left, const EvaluateResult& right) const { // Type mismatch always results in false if (model::GetTypeOrder(*left.value()) != model::GetTypeOrder(*right.value())) { @@ -881,7 +880,7 @@ EvaluateResult CoreCharLength::Evaluate( } } -EvaluateResult CoreStrConcat::Evaluate( +EvaluateResult CoreStringConcat::Evaluate( const api::EvaluateContext& context, const model::PipelineInputOutput& document) const { std::string result_string; @@ -928,8 +927,8 @@ EvaluateResult CoreStartsWith::PerformSearch(const std::string& value, nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); } -EvaluateResult CoreStrContains::PerformSearch(const std::string& value, - const std::string& search) const { +EvaluateResult CoreStringContains::PerformSearch( + const std::string& value, const std::string& search) const { // Use absl::StrContains bool result = absl::StrContains(value, search); return EvaluateResult::NewValue( @@ -1001,7 +1000,7 @@ EvaluateResult CoreTrim::Evaluate( } } -EvaluateResult CoreReverse::Evaluate( +EvaluateResult CoreStringReverse::Evaluate( const api::EvaluateContext& context, const model::PipelineInputOutput& document) const { HARD_ASSERT(expr_->params().size() == 1, @@ -1853,7 +1852,7 @@ EvaluateResult CoreIsError::Evaluate( } } -EvaluateResult CoreLogicalMaximum::Evaluate( +EvaluateResult CoreMaximum::Evaluate( const api::EvaluateContext& context, const model::PipelineInputOutput& document) const { // Store the underlying Value proto in the optional, not EvaluateResult @@ -1887,7 +1886,7 @@ EvaluateResult CoreLogicalMaximum::Evaluate( return EvaluateResult::NewNull(); } -EvaluateResult CoreLogicalMinimum::Evaluate( +EvaluateResult CoreMinimum::Evaluate( const api::EvaluateContext& context, const model::PipelineInputOutput& document) const { // Store the underlying Value proto in the optional, not EvaluateResult diff --git a/Firestore/core/src/core/expressions_eval.h b/Firestore/core/src/core/expressions_eval.h index c82060a7cb7..298d3e8b617 100644 --- a/Firestore/core/src/core/expressions_eval.h +++ b/Firestore/core/src/core/expressions_eval.h @@ -163,9 +163,9 @@ class ComparisonBase : public EvaluableExpr { std::unique_ptr expr_; }; -class CoreEq : public ComparisonBase { +class CoreEqual : public ComparisonBase { public: - explicit CoreEq(const api::FunctionExpr& expr) : ComparisonBase(expr) { + explicit CoreEqual(const api::FunctionExpr& expr) : ComparisonBase(expr) { } protected: @@ -173,9 +173,9 @@ class CoreEq : public ComparisonBase { const EvaluateResult& right) const override; }; -class CoreNeq : public ComparisonBase { +class CoreNotEqual : public ComparisonBase { public: - explicit CoreNeq(const api::FunctionExpr& expr) : ComparisonBase(expr) { + explicit CoreNotEqual(const api::FunctionExpr& expr) : ComparisonBase(expr) { } protected: @@ -183,9 +183,9 @@ class CoreNeq : public ComparisonBase { const EvaluateResult& right) const override; }; -class CoreLt : public ComparisonBase { +class CoreLessThan : public ComparisonBase { public: - explicit CoreLt(const api::FunctionExpr& expr) : ComparisonBase(expr) { + explicit CoreLessThan(const api::FunctionExpr& expr) : ComparisonBase(expr) { } protected: @@ -193,9 +193,10 @@ class CoreLt : public ComparisonBase { const EvaluateResult& right) const override; }; -class CoreLte : public ComparisonBase { +class CoreLessThanOrEqual : public ComparisonBase { public: - explicit CoreLte(const api::FunctionExpr& expr) : ComparisonBase(expr) { + explicit CoreLessThanOrEqual(const api::FunctionExpr& expr) + : ComparisonBase(expr) { } protected: @@ -203,9 +204,10 @@ class CoreLte : public ComparisonBase { const EvaluateResult& right) const override; }; -class CoreGt : public ComparisonBase { +class CoreGreaterThan : public ComparisonBase { public: - explicit CoreGt(const api::FunctionExpr& expr) : ComparisonBase(expr) { + explicit CoreGreaterThan(const api::FunctionExpr& expr) + : ComparisonBase(expr) { } protected: @@ -213,9 +215,10 @@ class CoreGt : public ComparisonBase { const EvaluateResult& right) const override; }; -class CoreGte : public ComparisonBase { +class CoreGreaterThanOrEqual : public ComparisonBase { public: - explicit CoreGte(const api::FunctionExpr& expr) : ComparisonBase(expr) { + explicit CoreGreaterThanOrEqual(const api::FunctionExpr& expr) + : ComparisonBase(expr) { } protected: @@ -431,9 +434,9 @@ class CoreCharLength : public EvaluableExpr { std::unique_ptr expr_; }; -class CoreStrConcat : public EvaluableExpr { +class CoreStringConcat : public EvaluableExpr { public: - explicit CoreStrConcat(const api::FunctionExpr& expr) + explicit CoreStringConcat(const api::FunctionExpr& expr) : expr_(std::make_unique(expr)) { } EvaluateResult Evaluate( @@ -466,9 +469,9 @@ class CoreStartsWith : public StringSearchBase { const std::string& search) const override; }; -class CoreStrContains : public StringSearchBase { +class CoreStringContains : public StringSearchBase { public: - explicit CoreStrContains(const api::FunctionExpr& expr) + explicit CoreStringContains(const api::FunctionExpr& expr) : StringSearchBase(expr) { } @@ -516,9 +519,9 @@ class CoreTrim : public EvaluableExpr { std::unique_ptr expr_; }; -class CoreReverse : public EvaluableExpr { +class CoreStringReverse : public EvaluableExpr { public: - explicit CoreReverse(const api::FunctionExpr& expr) + explicit CoreStringReverse(const api::FunctionExpr& expr) : expr_(std::make_unique(expr)) { } EvaluateResult Evaluate( @@ -721,9 +724,9 @@ class CoreIsError : public EvaluableExpr { std::unique_ptr expr_; }; -class CoreLogicalMaximum : public EvaluableExpr { +class CoreMaximum : public EvaluableExpr { public: - explicit CoreLogicalMaximum(const api::FunctionExpr& expr) + explicit CoreMaximum(const api::FunctionExpr& expr) : expr_(std::make_unique(expr)) { } EvaluateResult Evaluate( @@ -734,9 +737,9 @@ class CoreLogicalMaximum : public EvaluableExpr { std::unique_ptr expr_; }; -class CoreLogicalMinimum : public EvaluableExpr { +class CoreMinimum : public EvaluableExpr { public: - explicit CoreLogicalMinimum(const api::FunctionExpr& expr) + explicit CoreMinimum(const api::FunctionExpr& expr) : expr_(std::make_unique(expr)) { } EvaluateResult Evaluate( diff --git a/Firestore/core/src/core/pipeline_util.cc b/Firestore/core/src/core/pipeline_util.cc index 11531845d32..212a801f1bc 100644 --- a/Firestore/core/src/core/pipeline_util.cc +++ b/Firestore/core/src/core/pipeline_util.cc @@ -561,22 +561,22 @@ std::shared_ptr ToPipelineBooleanExpr(const Filter& filter) { switch (op) { case FieldFilter::Operator::LessThan: - func_name = "lt"; + func_name = "less_than"; break; case FieldFilter::Operator::LessThanOrEqual: - func_name = "lte"; + func_name = "less_than_or_equal"; break; case FieldFilter::Operator::GreaterThan: - func_name = "gt"; + func_name = "greater_than"; break; case FieldFilter::Operator::GreaterThanOrEqual: - func_name = "gte"; + func_name = "greater_than_or_equal"; break; case FieldFilter::Operator::Equal: - func_name = "eq"; + func_name = "equal"; break; case FieldFilter::Operator::NotEqual: - func_name = "neq"; + func_name = "not_equal"; break; case FieldFilter::Operator::ArrayContains: func_name = "array_contains"; @@ -589,9 +589,9 @@ std::shared_ptr ToPipelineBooleanExpr(const Filter& filter) { "Value for IN, NOT_IN, ARRAY_CONTAINS_ANY must be an array."); if (op == FieldFilter::Operator::In) - func_name = "eq_any"; + func_name = "equal_any"; else if (op == FieldFilter::Operator::NotIn) - func_name = "not_eq_any"; + func_name = "not_equal_any"; else if (op == FieldFilter::Operator::ArrayContainsAny) func_name = "array_contains_any"; break; @@ -635,8 +635,9 @@ std::shared_ptr WhereConditionsFromCursor( std::make_shared(model::DeepClone(pos->values[i]))); } - std::string func_name = is_before ? "lt" : "gt"; - std::string func_inclusive_name = is_before ? "lte" : "gte"; + std::string func_name = is_before ? "less_than" : "greater_than"; + std::string func_inclusive_name = + is_before ? "less_than_or_equal" : "greater_than_or_equal"; std::vector> or_conditions; for (size_t sub_end = 1; sub_end <= cursors.size(); ++sub_end) { diff --git a/Firestore/core/test/unit/core/expressions/comparison_test.cc b/Firestore/core/test/unit/core/expressions/comparison_test.cc index 1113fd5d4b6..141b803941c 100644 --- a/Firestore/core/test/unit/core/expressions/comparison_test.cc +++ b/Firestore/core/test/unit/core/expressions/comparison_test.cc @@ -26,7 +26,7 @@ #include "Firestore/core/src/model/database_id.h" // For DatabaseId #include "Firestore/core/src/model/document_key.h" // For DocumentKey #include "Firestore/core/src/model/value_util.h" // For value constants like NaNValue, TypeOrder, NullValue, CanonicalId, Equals -#include "Firestore/core/test/unit/testutil/expression_test_util.h" // For EvaluateExpr, EqExpr, ComparisonValueTestData, RefConstant etc. +#include "Firestore/core/test/unit/testutil/expression_test_util.h" // For EvaluateExpr, EqualExpr, ComparisonValueTestData, RefConstant etc. #include "Firestore/core/test/unit/testutil/testutil.h" // For test helpers like Value, Array, Map, BlobValue, Doc #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -42,13 +42,13 @@ using model::MutableDocument; // Used as PipelineInputOutput alias using testing::_; // Explicitly qualify testutil helpers to avoid ambiguity using testutil::ComparisonValueTestData; -using testutil::EqExpr; +using testutil::EqualExpr; using testutil::EvaluateExpr; -using testutil::GteExpr; -using testutil::GtExpr; -using testutil::LteExpr; -using testutil::LtExpr; -using testutil::NeqExpr; +using testutil::GreaterThanExpr; +using testutil::GreaterThanOrEqualExpr; +using testutil::LessThanExpr; +using testutil::LessThanOrEqualExpr; +using testutil::NotEqualExpr; using testutil::RefConstant; using testutil::Returns; using testutil::ReturnsError; @@ -61,8 +61,8 @@ class ComparisonExpressionsTest : public ::testing::Test { // Helper moved to expression_test_util.h }; -// Fixture for Eq function tests -class EqFunctionTest : public ComparisonExpressionsTest {}; +// Fixture for Equal function tests +class EqualFunctionTest : public ComparisonExpressionsTest {}; // Helper to get canonical ID for logging, handling potential non-constant exprs std::string ExprId(const std::shared_ptr& expr) { @@ -75,95 +75,95 @@ std::string ExprId(const std::shared_ptr& expr) { return ""; } -TEST_F(EqFunctionTest, EquivalentValuesReturnTrue) { +TEST_F(EqualFunctionTest, EquivalentValuesReturnTrue) { for (const auto& pair : ComparisonValueTestData::EquivalentValues()) { - EXPECT_THAT(EvaluateExpr(*EqExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*EqualExpr({pair.first, pair.second})), Returns(testutil::Value(true))) - << "eq(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "equal(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; } } -TEST_F(EqFunctionTest, LessThanValuesReturnFalse) { +TEST_F(EqualFunctionTest, LessThanValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::LessThanValues()) { - EXPECT_THAT(EvaluateExpr(*EqExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*EqualExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "eq(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "equal(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; } } -TEST_F(EqFunctionTest, GreaterThanValuesReturnFalse) { +TEST_F(EqualFunctionTest, GreaterThanValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::GreaterThanValues()) { - EXPECT_THAT(EvaluateExpr(*EqExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*EqualExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "eq(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "equal(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; } } -TEST_F(EqFunctionTest, MixedTypeValuesReturnFalse) { +TEST_F(EqualFunctionTest, MixedTypeValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::MixedTypeValues()) { - EXPECT_THAT(EvaluateExpr(*EqExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*EqualExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "eq(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "equal(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; } } -// --- Specific Eq Tests (Null, NaN, Missing, Error) --- +// --- Specific Equal Tests (Null, NaN, Missing, Error) --- -// Fixture for Neq function tests -class NeqFunctionTest : public ComparisonExpressionsTest {}; +// Fixture for NotEqual function tests +class NotEqualFunctionTest : public ComparisonExpressionsTest {}; -// Fixture for Lt function tests -class LtFunctionTest : public ComparisonExpressionsTest {}; +// Fixture for LessThan function tests +class LessThanFunctionTest : public ComparisonExpressionsTest {}; -// Fixture for Lte function tests -class LteFunctionTest : public ComparisonExpressionsTest {}; +// Fixture for LessThanOrEqual function tests +class LessThanOrEqualFunctionTest : public ComparisonExpressionsTest {}; -// Fixture for Gt function tests -class GtFunctionTest : public ComparisonExpressionsTest {}; +// Fixture for GreaterThan function tests +class GreaterThanFunctionTest : public ComparisonExpressionsTest {}; -// Fixture for Gte function tests -class GteFunctionTest : public ComparisonExpressionsTest {}; +// Fixture for GreaterThanOrEqual function tests +class GreaterThanOrEqualFunctionTest : public ComparisonExpressionsTest {}; -// --- Eq (==) Tests --- +// --- Equal (==) Tests --- -TEST_F(EqFunctionTest, NullEqualsNullReturnsNull) { - EXPECT_THAT(EvaluateExpr(*EqExpr({SharedConstant(model::NullValue()), - SharedConstant(model::NullValue())})), +TEST_F(EqualFunctionTest, NullEqualsNullReturnsNull) { + EXPECT_THAT(EvaluateExpr(*EqualExpr({SharedConstant(model::NullValue()), + SharedConstant(model::NullValue())})), ReturnsNull()); } // Corresponds to eq.null_any_returnsNull in typescript -TEST_F(EqFunctionTest, NullOperandReturnsNull) { +TEST_F(EqualFunctionTest, NullOperandReturnsNull) { for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { EXPECT_THAT( - EvaluateExpr(*EqExpr({SharedConstant(model::NullValue()), val})), + EvaluateExpr(*EqualExpr({SharedConstant(model::NullValue()), val})), ReturnsNull()) - << "eq(null, " << ExprId(val) << ")"; + << "equal(null, " << ExprId(val) << ")"; EXPECT_THAT( - EvaluateExpr(*EqExpr({val, SharedConstant(model::NullValue())})), + EvaluateExpr(*EqualExpr({val, SharedConstant(model::NullValue())})), ReturnsNull()) - << "eq(" << ExprId(val) << ", null)"; + << "equal(" << ExprId(val) << ", null)"; } EXPECT_THAT( - EvaluateExpr(*EqExpr({SharedConstant(model::NullValue()), - std::make_shared("nonexistent")})), + EvaluateExpr(*EqualExpr({SharedConstant(model::NullValue()), + std::make_shared("nonexistent")})), ReturnsError()); } // Corresponds to eq.nan tests in typescript -TEST_F(EqFunctionTest, NaNComparisonsReturnFalse) { +TEST_F(EqualFunctionTest, NaNComparisonsReturnFalse) { auto nan_expr = SharedConstant(std::numeric_limits::quiet_NaN()); - EXPECT_THAT(EvaluateExpr(*EqExpr({nan_expr, nan_expr})), + EXPECT_THAT(EvaluateExpr(*EqualExpr({nan_expr, nan_expr})), Returns(testutil::Value(false))); // NaN == NaN is false for (const auto& num_val : ComparisonValueTestData::NumericValues()) { - EXPECT_THAT(EvaluateExpr(*EqExpr({nan_expr, num_val})), + EXPECT_THAT(EvaluateExpr(*EqualExpr({nan_expr, num_val})), Returns(testutil::Value(false))) - << "eq(NaN, " << ExprId(num_val) << ")"; - EXPECT_THAT(EvaluateExpr(*EqExpr({num_val, nan_expr})), + << "equal(NaN, " << ExprId(num_val) << ")"; + EXPECT_THAT(EvaluateExpr(*EqualExpr({num_val, nan_expr})), Returns(testutil::Value(false))) - << "eq(" << ExprId(num_val) << ", NaN)"; + << "equal(" << ExprId(num_val) << ", NaN)"; } for (const auto& other_val : @@ -176,23 +176,23 @@ TEST_F(EqFunctionTest, NaNComparisonsReturnFalse) { } } if (!is_numeric) { - EXPECT_THAT(EvaluateExpr(*EqExpr({nan_expr, other_val})), + EXPECT_THAT(EvaluateExpr(*EqualExpr({nan_expr, other_val})), Returns(testutil::Value(false))) - << "eq(NaN, " << ExprId(other_val) << ")"; - EXPECT_THAT(EvaluateExpr(*EqExpr({other_val, nan_expr})), + << "equal(NaN, " << ExprId(other_val) << ")"; + EXPECT_THAT(EvaluateExpr(*EqualExpr({other_val, nan_expr})), Returns(testutil::Value(false))) - << "eq(" << ExprId(other_val) << ", NaN)"; + << "equal(" << ExprId(other_val) << ", NaN)"; } } + EXPECT_THAT(EvaluateExpr(*EqualExpr( + {SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN()))), + SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN())))})), + Returns(testutil::Value(false))); EXPECT_THAT( - EvaluateExpr(*EqExpr({SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN()))), - SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN())))})), - Returns(testutil::Value(false))); - EXPECT_THAT( - EvaluateExpr(*EqExpr( + EvaluateExpr(*EqualExpr( {SharedConstant(testutil::Map( "foo", testutil::Value(std::numeric_limits::quiet_NaN()))), @@ -204,148 +204,153 @@ TEST_F(EqFunctionTest, NaNComparisonsReturnFalse) { // Corresponds to eq.nullInArray_equality / eq.nullInMap_equality / // eq.null_missingInMap_equality -TEST_F(EqFunctionTest, NullContainerEquality) { +TEST_F(EqualFunctionTest, NullContainerEquality) { auto null_array = SharedConstant(testutil::Array(testutil::Value(nullptr))); - EXPECT_THAT(EvaluateExpr(*EqExpr( + EXPECT_THAT(EvaluateExpr(*EqualExpr( {null_array, SharedConstant(static_cast(1LL))})), Returns(testutil::Value(false))); - EXPECT_THAT(EvaluateExpr(*EqExpr({null_array, SharedConstant("1")})), + EXPECT_THAT(EvaluateExpr(*EqualExpr({null_array, SharedConstant("1")})), Returns(testutil::Value(false))); - EXPECT_THAT( - EvaluateExpr(*EqExpr({null_array, SharedConstant(model::NullValue())})), - ReturnsNull()); - EXPECT_THAT(EvaluateExpr(*EqExpr( + EXPECT_THAT(EvaluateExpr( + *EqualExpr({null_array, SharedConstant(model::NullValue())})), + ReturnsNull()); + EXPECT_THAT(EvaluateExpr(*EqualExpr( {null_array, SharedConstant(std::numeric_limits::quiet_NaN())})), Returns(testutil::Value(false))); EXPECT_THAT( - EvaluateExpr(*EqExpr({null_array, SharedConstant(testutil::Array())})), + EvaluateExpr(*EqualExpr({null_array, SharedConstant(testutil::Array())})), Returns(testutil::Value(false))); EXPECT_THAT( - EvaluateExpr(*EqExpr( + EvaluateExpr(*EqualExpr( {null_array, SharedConstant(testutil::Array(testutil::Value( std::numeric_limits::quiet_NaN())))})), ReturnsNull()); EXPECT_THAT( - EvaluateExpr(*EqExpr({null_array, SharedConstant(testutil::Array( - testutil::Value(nullptr)))})), + EvaluateExpr(*EqualExpr({null_array, SharedConstant(testutil::Array( + testutil::Value(nullptr)))})), ReturnsNull()); auto null_map = SharedConstant(testutil::Map("foo", testutil::Value(nullptr))); + EXPECT_THAT(EvaluateExpr(*EqualExpr( + {null_map, SharedConstant(testutil::Map( + "foo", testutil::Value(nullptr)))})), + ReturnsNull()); EXPECT_THAT( - EvaluateExpr(*EqExpr({null_map, SharedConstant(testutil::Map( - "foo", testutil::Value(nullptr)))})), - ReturnsNull()); - EXPECT_THAT( - EvaluateExpr(*EqExpr({null_map, SharedConstant(testutil::Map())})), + EvaluateExpr(*EqualExpr({null_map, SharedConstant(testutil::Map())})), Returns(testutil::Value(false))); } // Corresponds to eq.error_ tests -TEST_F(EqFunctionTest, ErrorHandling) { +TEST_F(EqualFunctionTest, ErrorHandling) { auto error_expr = std::make_shared("a.b"); auto non_map_input = testutil::Doc("coll/doc", 1, testutil::Map("a", 123)); for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { - EXPECT_THAT(EvaluateExpr(*EqExpr({error_expr, val}), non_map_input), + EXPECT_THAT(EvaluateExpr(*EqualExpr({error_expr, val}), non_map_input), ReturnsError()); - EXPECT_THAT(EvaluateExpr(*EqExpr({val, error_expr}), non_map_input), + EXPECT_THAT(EvaluateExpr(*EqualExpr({val, error_expr}), non_map_input), ReturnsError()); } - EXPECT_THAT(EvaluateExpr(*EqExpr({error_expr, error_expr}), non_map_input), + EXPECT_THAT(EvaluateExpr(*EqualExpr({error_expr, error_expr}), non_map_input), ReturnsError()); EXPECT_THAT( - EvaluateExpr(*EqExpr({error_expr, SharedConstant(model::NullValue())}), + EvaluateExpr(*EqualExpr({error_expr, SharedConstant(model::NullValue())}), non_map_input), ReturnsError()); } -TEST_F(EqFunctionTest, MissingFieldReturnsError) { - EXPECT_THAT(EvaluateExpr(*EqExpr({std::make_shared("nonexistent"), - SharedConstant(testutil::Value(1LL))})), - ReturnsError()); +TEST_F(EqualFunctionTest, MissingFieldReturnsError) { EXPECT_THAT( - EvaluateExpr(*EqExpr({SharedConstant(testutil::Value(1LL)), - std::make_shared("nonexistent")})), + EvaluateExpr(*EqualExpr({std::make_shared("nonexistent"), + SharedConstant(testutil::Value(1LL))})), + ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*EqualExpr({SharedConstant(testutil::Value(1LL)), + std::make_shared("nonexistent")})), ReturnsError()); } -// --- Neq (!=) Tests --- +// --- NotEqual (!=) Tests --- -TEST_F(NeqFunctionTest, EquivalentValuesReturnFalse) { +TEST_F(NotEqualFunctionTest, EquivalentValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::EquivalentValues()) { - EXPECT_THAT(EvaluateExpr(*NeqExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "neq(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "not_equal(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -TEST_F(NeqFunctionTest, LessThanValuesReturnTrue) { +TEST_F(NotEqualFunctionTest, LessThanValuesReturnTrue) { for (const auto& pair : ComparisonValueTestData::LessThanValues()) { - EXPECT_THAT(EvaluateExpr(*NeqExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({pair.first, pair.second})), Returns(testutil::Value(true))) - << "neq(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "not_equal(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -TEST_F(NeqFunctionTest, GreaterThanValuesReturnTrue) { +TEST_F(NotEqualFunctionTest, GreaterThanValuesReturnTrue) { for (const auto& pair : ComparisonValueTestData::GreaterThanValues()) { - EXPECT_THAT(EvaluateExpr(*NeqExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({pair.first, pair.second})), Returns(testutil::Value(true))) - << "neq(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "not_equal(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -TEST_F(NeqFunctionTest, MixedTypeValuesReturnTrue) { +TEST_F(NotEqualFunctionTest, MixedTypeValuesReturnTrue) { for (const auto& pair : ComparisonValueTestData::MixedTypeValues()) { - EXPECT_THAT(EvaluateExpr(*NeqExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({pair.first, pair.second})), Returns(testutil::Value(true))) - << "neq(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "not_equal(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -// --- Specific Neq Tests --- +// --- Specific NotEqual Tests --- -TEST_F(NeqFunctionTest, NullNotEqualsNullReturnsNull) { - EXPECT_THAT(EvaluateExpr(*NeqExpr({SharedConstant(model::NullValue()), - SharedConstant(model::NullValue())})), +TEST_F(NotEqualFunctionTest, NullNotEqualsNullReturnsNull) { + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({SharedConstant(model::NullValue()), + SharedConstant(model::NullValue())})), ReturnsNull()); } // Corresponds to neq.null_any_returnsNull -TEST_F(NeqFunctionTest, NullOperandReturnsNull) { +TEST_F(NotEqualFunctionTest, NullOperandReturnsNull) { for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { EXPECT_THAT( - EvaluateExpr(*NeqExpr({SharedConstant(model::NullValue()), val})), + EvaluateExpr(*NotEqualExpr({SharedConstant(model::NullValue()), val})), ReturnsNull()) - << "neq(null, " << ExprId(val) << ")"; + << "not_equal(null, " << ExprId(val) << ")"; EXPECT_THAT( - EvaluateExpr(*NeqExpr({val, SharedConstant(model::NullValue())})), + EvaluateExpr(*NotEqualExpr({val, SharedConstant(model::NullValue())})), ReturnsNull()) - << "neq(" << ExprId(val) << ", null)"; + << "not_equal(" << ExprId(val) << ", null)"; } - EXPECT_THAT( - EvaluateExpr(*NeqExpr({SharedConstant(model::NullValue()), - std::make_shared("nonexistent")})), - ReturnsError()); + EXPECT_THAT(EvaluateExpr( + *NotEqualExpr({SharedConstant(model::NullValue()), + std::make_shared("nonexistent")})), + ReturnsError()); } // Corresponds to neq.nan tests -TEST_F(NeqFunctionTest, NaNComparisonsReturnTrue) { +TEST_F(NotEqualFunctionTest, NaNComparisonsReturnTrue) { auto nan_expr = SharedConstant(std::numeric_limits::quiet_NaN()); - EXPECT_THAT(EvaluateExpr(*NeqExpr({nan_expr, nan_expr})), + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({nan_expr, nan_expr})), Returns(testutil::Value(true))); // NaN != NaN is true for (const auto& num_val : ComparisonValueTestData::NumericValues()) { - EXPECT_THAT(EvaluateExpr(*NeqExpr({nan_expr, num_val})), + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({nan_expr, num_val})), Returns(testutil::Value(true))) - << "neq(NaN, " << ExprId(num_val) << ")"; - EXPECT_THAT(EvaluateExpr(*NeqExpr({num_val, nan_expr})), + << "not_equal(NaN, " << ExprId(num_val) << ")"; + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({num_val, nan_expr})), Returns(testutil::Value(true))) - << "neq(" << ExprId(num_val) << ", NaN)"; + << "not_equal(" << ExprId(num_val) << ", NaN)"; } for (const auto& other_val : @@ -358,23 +363,23 @@ TEST_F(NeqFunctionTest, NaNComparisonsReturnTrue) { } } if (!is_numeric) { - EXPECT_THAT(EvaluateExpr(*NeqExpr({nan_expr, other_val})), + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({nan_expr, other_val})), Returns(testutil::Value(true))) - << "neq(NaN, " << ExprId(other_val) << ")"; - EXPECT_THAT(EvaluateExpr(*NeqExpr({other_val, nan_expr})), + << "not_equal(NaN, " << ExprId(other_val) << ")"; + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({other_val, nan_expr})), Returns(testutil::Value(true))) - << "neq(" << ExprId(other_val) << ", NaN)"; + << "not_equal(" << ExprId(other_val) << ", NaN)"; } } + EXPECT_THAT(EvaluateExpr(*NotEqualExpr( + {SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN()))), + SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN())))})), + Returns(testutil::Value(true))); EXPECT_THAT( - EvaluateExpr(*NeqExpr({SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN()))), - SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN())))})), - Returns(testutil::Value(true))); - EXPECT_THAT( - EvaluateExpr(*NeqExpr( + EvaluateExpr(*NotEqualExpr( {SharedConstant(testutil::Map( "foo", testutil::Value(std::numeric_limits::quiet_NaN()))), @@ -385,110 +390,115 @@ TEST_F(NeqFunctionTest, NaNComparisonsReturnTrue) { } // Corresponds to neq.error_ tests -TEST_F(NeqFunctionTest, ErrorHandling) { +TEST_F(NotEqualFunctionTest, ErrorHandling) { auto error_expr = std::make_shared("a.b"); auto non_map_input = testutil::Doc("coll/doc", 1, testutil::Map("a", 123)); for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { - EXPECT_THAT(EvaluateExpr(*NeqExpr({error_expr, val}), non_map_input), + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({error_expr, val}), non_map_input), ReturnsError()); - EXPECT_THAT(EvaluateExpr(*NeqExpr({val, error_expr}), non_map_input), + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({val, error_expr}), non_map_input), ReturnsError()); } - EXPECT_THAT(EvaluateExpr(*NeqExpr({error_expr, error_expr}), non_map_input), - ReturnsError()); EXPECT_THAT( - EvaluateExpr(*NeqExpr({error_expr, SharedConstant(model::NullValue())}), - non_map_input), + EvaluateExpr(*NotEqualExpr({error_expr, error_expr}), non_map_input), ReturnsError()); + EXPECT_THAT(EvaluateExpr(*NotEqualExpr({error_expr, + SharedConstant(model::NullValue())}), + non_map_input), + ReturnsError()); } -TEST_F(NeqFunctionTest, MissingFieldReturnsError) { +TEST_F(NotEqualFunctionTest, MissingFieldReturnsError) { EXPECT_THAT( - EvaluateExpr(*NeqExpr({std::make_shared("nonexistent"), - SharedConstant(testutil::Value(1LL))})), - ReturnsError()); - EXPECT_THAT( - EvaluateExpr(*NeqExpr({SharedConstant(testutil::Value(1LL)), - std::make_shared("nonexistent")})), + EvaluateExpr(*NotEqualExpr({std::make_shared("nonexistent"), + SharedConstant(testutil::Value(1LL))})), ReturnsError()); + EXPECT_THAT(EvaluateExpr( + *NotEqualExpr({SharedConstant(testutil::Value(1LL)), + std::make_shared("nonexistent")})), + ReturnsError()); } -// --- Lt (<) Tests --- +// --- LessThan (<) Tests --- -TEST_F(LtFunctionTest, EquivalentValuesReturnFalse) { +TEST_F(LessThanFunctionTest, EquivalentValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::EquivalentValues()) { - EXPECT_THAT(EvaluateExpr(*LtExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*LessThanExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "lt(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "less_than(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -TEST_F(LtFunctionTest, LessThanValuesReturnTrue) { +TEST_F(LessThanFunctionTest, LessThanValuesReturnTrue) { for (const auto& pair : ComparisonValueTestData::LessThanValues()) { auto left_const = std::dynamic_pointer_cast(pair.first); auto right_const = std::dynamic_pointer_cast(pair.second); // Use model::Equals to check for non-equal comparable pairs - EXPECT_THAT(EvaluateExpr(*LtExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*LessThanExpr({pair.first, pair.second})), Returns(testutil::Value(true))) - << "lt(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "less_than(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -TEST_F(LtFunctionTest, GreaterThanValuesReturnFalse) { +TEST_F(LessThanFunctionTest, GreaterThanValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::GreaterThanValues()) { - EXPECT_THAT(EvaluateExpr(*LtExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*LessThanExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "lt(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "less_than(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -TEST_F(LtFunctionTest, MixedTypeValuesReturnFalse) { +TEST_F(LessThanFunctionTest, MixedTypeValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::MixedTypeValues()) { - EXPECT_THAT(EvaluateExpr(*LtExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*LessThanExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "lt(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "less_than(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -// --- Specific Lt Tests --- +// --- Specific LessThan Tests --- -TEST_F(LtFunctionTest, NullOperandReturnsNull) { +TEST_F(LessThanFunctionTest, NullOperandReturnsNull) { for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { EXPECT_THAT( - EvaluateExpr(*LtExpr({SharedConstant(model::NullValue()), val})), + EvaluateExpr(*LessThanExpr({SharedConstant(model::NullValue()), val})), ReturnsNull()) - << "lt(null, " << ExprId(val) << ")"; + << "less_than(null, " << ExprId(val) << ")"; EXPECT_THAT( - EvaluateExpr(*LtExpr({val, SharedConstant(model::NullValue())})), + EvaluateExpr(*LessThanExpr({val, SharedConstant(model::NullValue())})), ReturnsNull()) - << "lt(" << ExprId(val) << ", null)"; + << "less_than(" << ExprId(val) << ", null)"; } - EXPECT_THAT(EvaluateExpr(*LtExpr({SharedConstant(model::NullValue()), - SharedConstant(model::NullValue())})), + EXPECT_THAT(EvaluateExpr(*LessThanExpr({SharedConstant(model::NullValue()), + SharedConstant(model::NullValue())})), ReturnsNull()); - EXPECT_THAT( - EvaluateExpr(*LtExpr({SharedConstant(model::NullValue()), - std::make_shared("nonexistent")})), - ReturnsError()); + EXPECT_THAT(EvaluateExpr( + *LessThanExpr({SharedConstant(model::NullValue()), + std::make_shared("nonexistent")})), + ReturnsError()); } -TEST_F(LtFunctionTest, NaNComparisonsReturnFalse) { +TEST_F(LessThanFunctionTest, NaNComparisonsReturnFalse) { auto nan_expr = SharedConstant(std::numeric_limits::quiet_NaN()); - EXPECT_THAT(EvaluateExpr(*LtExpr({nan_expr, nan_expr})), + EXPECT_THAT(EvaluateExpr(*LessThanExpr({nan_expr, nan_expr})), Returns(testutil::Value(false))); for (const auto& num_val : ComparisonValueTestData::NumericValues()) { - EXPECT_THAT(EvaluateExpr(*LtExpr({nan_expr, num_val})), + EXPECT_THAT(EvaluateExpr(*LessThanExpr({nan_expr, num_val})), Returns(testutil::Value(false))) - << "lt(NaN, " << ExprId(num_val) << ")"; - EXPECT_THAT(EvaluateExpr(*LtExpr({num_val, nan_expr})), + << "less_than(NaN, " << ExprId(num_val) << ")"; + EXPECT_THAT(EvaluateExpr(*LessThanExpr({num_val, nan_expr})), Returns(testutil::Value(false))) - << "lt(" << ExprId(num_val) << ", NaN)"; + << "less_than(" << ExprId(num_val) << ", NaN)"; } for (const auto& other_val : ComparisonValueTestData::AllSupportedComparableValues()) { @@ -500,120 +510,127 @@ TEST_F(LtFunctionTest, NaNComparisonsReturnFalse) { } } if (!is_numeric) { - EXPECT_THAT(EvaluateExpr(*LtExpr({nan_expr, other_val})), + EXPECT_THAT(EvaluateExpr(*LessThanExpr({nan_expr, other_val})), Returns(testutil::Value(false))) - << "lt(NaN, " << ExprId(other_val) << ")"; - EXPECT_THAT(EvaluateExpr(*LtExpr({other_val, nan_expr})), + << "less_than(NaN, " << ExprId(other_val) << ")"; + EXPECT_THAT(EvaluateExpr(*LessThanExpr({other_val, nan_expr})), Returns(testutil::Value(false))) - << "lt(" << ExprId(other_val) << ", NaN)"; + << "less_than(" << ExprId(other_val) << ", NaN)"; } } - EXPECT_THAT( - EvaluateExpr(*LtExpr({SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN()))), - SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN())))})), - Returns(testutil::Value(false))); + EXPECT_THAT(EvaluateExpr(*LessThanExpr( + {SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN()))), + SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN())))})), + Returns(testutil::Value(false))); } -TEST_F(LtFunctionTest, ErrorHandling) { +TEST_F(LessThanFunctionTest, ErrorHandling) { auto error_expr = std::make_shared("a.b"); auto non_map_input = testutil::Doc("coll/doc", 1, testutil::Map("a", 123)); for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { - EXPECT_THAT(EvaluateExpr(*LtExpr({error_expr, val}), non_map_input), + EXPECT_THAT(EvaluateExpr(*LessThanExpr({error_expr, val}), non_map_input), ReturnsError()); - EXPECT_THAT(EvaluateExpr(*LtExpr({val, error_expr}), non_map_input), + EXPECT_THAT(EvaluateExpr(*LessThanExpr({val, error_expr}), non_map_input), ReturnsError()); } - EXPECT_THAT(EvaluateExpr(*LtExpr({error_expr, error_expr}), non_map_input), - ReturnsError()); EXPECT_THAT( - EvaluateExpr(*LtExpr({error_expr, SharedConstant(model::NullValue())}), - non_map_input), + EvaluateExpr(*LessThanExpr({error_expr, error_expr}), non_map_input), ReturnsError()); + EXPECT_THAT(EvaluateExpr(*LessThanExpr({error_expr, + SharedConstant(model::NullValue())}), + non_map_input), + ReturnsError()); } -TEST_F(LtFunctionTest, MissingFieldReturnsError) { - EXPECT_THAT(EvaluateExpr(*LtExpr({std::make_shared("nonexistent"), - SharedConstant(testutil::Value(1LL))})), - ReturnsError()); +TEST_F(LessThanFunctionTest, MissingFieldReturnsError) { EXPECT_THAT( - EvaluateExpr(*LtExpr({SharedConstant(testutil::Value(1LL)), - std::make_shared("nonexistent")})), + EvaluateExpr(*LessThanExpr({std::make_shared("nonexistent"), + SharedConstant(testutil::Value(1LL))})), ReturnsError()); + EXPECT_THAT(EvaluateExpr( + *LessThanExpr({SharedConstant(testutil::Value(1LL)), + std::make_shared("nonexistent")})), + ReturnsError()); } -// --- Lte (<=) Tests --- +// --- LessThanOrEqual (<=) Tests --- -TEST_F(LteFunctionTest, EquivalentValuesReturnTrue) { +TEST_F(LessThanOrEqualFunctionTest, EquivalentValuesReturnTrue) { for (const auto& pair : ComparisonValueTestData::EquivalentValues()) { - EXPECT_THAT(EvaluateExpr(*LteExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr({pair.first, pair.second})), Returns(testutil::Value(true))) - << "lte(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "less_than_or_equal(" << ExprId(pair.first) << ", " + << ExprId(pair.second) << ")"; } } -TEST_F(LteFunctionTest, LessThanValuesReturnTrue) { +TEST_F(LessThanOrEqualFunctionTest, LessThanValuesReturnTrue) { for (const auto& pair : ComparisonValueTestData::LessThanValues()) { - EXPECT_THAT(EvaluateExpr(*LteExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr({pair.first, pair.second})), Returns(testutil::Value(true))) - << "lte(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "less_than_or_equal(" << ExprId(pair.first) << ", " + << ExprId(pair.second) << ")"; } } -TEST_F(LteFunctionTest, GreaterThanValuesReturnFalse) { +TEST_F(LessThanOrEqualFunctionTest, GreaterThanValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::GreaterThanValues()) { - EXPECT_THAT(EvaluateExpr(*LteExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "lte(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "less_than_or_equal(" << ExprId(pair.first) << ", " + << ExprId(pair.second) << ")"; } } -TEST_F(LteFunctionTest, MixedTypeValuesReturnFalse) { +TEST_F(LessThanOrEqualFunctionTest, MixedTypeValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::MixedTypeValues()) { - EXPECT_THAT(EvaluateExpr(*LteExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "lte(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "less_than_or_equal(" << ExprId(pair.first) << ", " + << ExprId(pair.second) << ")"; } } -// --- Specific Lte Tests --- +// --- Specific LessThanOrEqual Tests --- -TEST_F(LteFunctionTest, NullOperandReturnsNull) { +TEST_F(LessThanOrEqualFunctionTest, NullOperandReturnsNull) { for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { - EXPECT_THAT( - EvaluateExpr(*LteExpr({SharedConstant(model::NullValue()), val})), - ReturnsNull()) - << "lte(null, " << ExprId(val) << ")"; - EXPECT_THAT( - EvaluateExpr(*LteExpr({val, SharedConstant(model::NullValue())})), - ReturnsNull()) - << "lte(" << ExprId(val) << ", null)"; - } - EXPECT_THAT(EvaluateExpr(*LteExpr({SharedConstant(model::NullValue()), - SharedConstant(model::NullValue())})), - ReturnsNull()); - EXPECT_THAT( - EvaluateExpr(*LteExpr({SharedConstant(model::NullValue()), - std::make_shared("nonexistent")})), - ReturnsError()); + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr( + {SharedConstant(model::NullValue()), val})), + ReturnsNull()) + << "less_than_or_equal(null, " << ExprId(val) << ")"; + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr( + {val, SharedConstant(model::NullValue())})), + ReturnsNull()) + << "less_than_or_equal(" << ExprId(val) << ", null)"; + } + EXPECT_THAT( + EvaluateExpr(*LessThanOrEqualExpr({SharedConstant(model::NullValue()), + SharedConstant(model::NullValue())})), + ReturnsNull()); + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr( + {SharedConstant(model::NullValue()), + std::make_shared("nonexistent")})), + ReturnsError()); } -TEST_F(LteFunctionTest, NaNComparisonsReturnFalse) { +TEST_F(LessThanOrEqualFunctionTest, NaNComparisonsReturnFalse) { auto nan_expr = SharedConstant(std::numeric_limits::quiet_NaN()); - EXPECT_THAT(EvaluateExpr(*LteExpr({nan_expr, nan_expr})), + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr({nan_expr, nan_expr})), Returns(testutil::Value(false))); for (const auto& num_val : ComparisonValueTestData::NumericValues()) { - EXPECT_THAT(EvaluateExpr(*LteExpr({nan_expr, num_val})), + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr({nan_expr, num_val})), Returns(testutil::Value(false))) - << "lte(NaN, " << ExprId(num_val) << ")"; - EXPECT_THAT(EvaluateExpr(*LteExpr({num_val, nan_expr})), + << "less_than_or_equal(NaN, " << ExprId(num_val) << ")"; + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr({num_val, nan_expr})), Returns(testutil::Value(false))) - << "lte(" << ExprId(num_val) << ", NaN)"; + << "less_than_or_equal(" << ExprId(num_val) << ", NaN)"; } for (const auto& other_val : ComparisonValueTestData::AllSupportedComparableValues()) { @@ -625,71 +642,77 @@ TEST_F(LteFunctionTest, NaNComparisonsReturnFalse) { } } if (!is_numeric) { - EXPECT_THAT(EvaluateExpr(*LteExpr({nan_expr, other_val})), + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr({nan_expr, other_val})), Returns(testutil::Value(false))) - << "lte(NaN, " << ExprId(other_val) << ")"; - EXPECT_THAT(EvaluateExpr(*LteExpr({other_val, nan_expr})), + << "less_than_or_equal(NaN, " << ExprId(other_val) << ")"; + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr({other_val, nan_expr})), Returns(testutil::Value(false))) - << "lte(" << ExprId(other_val) << ", NaN)"; + << "less_than_or_equal(" << ExprId(other_val) << ", NaN)"; } } - EXPECT_THAT( - EvaluateExpr(*LteExpr({SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN()))), - SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN())))})), - Returns(testutil::Value(false))); + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr( + {SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN()))), + SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN())))})), + Returns(testutil::Value(false))); } -TEST_F(LteFunctionTest, ErrorHandling) { +TEST_F(LessThanOrEqualFunctionTest, ErrorHandling) { auto error_expr = std::make_shared("a.b"); auto non_map_input = testutil::Doc("coll/doc", 1, testutil::Map("a", 123)); for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { - EXPECT_THAT(EvaluateExpr(*LteExpr({error_expr, val}), non_map_input), - ReturnsError()); - EXPECT_THAT(EvaluateExpr(*LteExpr({val, error_expr}), non_map_input), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*LessThanOrEqualExpr({error_expr, val}), non_map_input), + ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*LessThanOrEqualExpr({val, error_expr}), non_map_input), + ReturnsError()); } - EXPECT_THAT(EvaluateExpr(*LteExpr({error_expr, error_expr}), non_map_input), + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr({error_expr, error_expr}), + non_map_input), ReturnsError()); EXPECT_THAT( - EvaluateExpr(*LteExpr({error_expr, SharedConstant(model::NullValue())}), + EvaluateExpr(*LessThanOrEqualExpr( + {error_expr, SharedConstant(model::NullValue())}), non_map_input), ReturnsError()); } -TEST_F(LteFunctionTest, MissingFieldReturnsError) { - EXPECT_THAT( - EvaluateExpr(*LteExpr({std::make_shared("nonexistent"), - SharedConstant(testutil::Value(1LL))})), - ReturnsError()); - EXPECT_THAT( - EvaluateExpr(*LteExpr({SharedConstant(testutil::Value(1LL)), - std::make_shared("nonexistent")})), - ReturnsError()); +TEST_F(LessThanOrEqualFunctionTest, MissingFieldReturnsError) { + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr( + {std::make_shared("nonexistent"), + SharedConstant(testutil::Value(1LL))})), + ReturnsError()); + EXPECT_THAT(EvaluateExpr(*LessThanOrEqualExpr( + {SharedConstant(testutil::Value(1LL)), + std::make_shared("nonexistent")})), + ReturnsError()); } -// --- Gt (>) Tests --- +// --- GreaterThan (>) Tests --- -TEST_F(GtFunctionTest, EquivalentValuesReturnFalse) { +TEST_F(GreaterThanFunctionTest, EquivalentValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::EquivalentValues()) { - EXPECT_THAT(EvaluateExpr(*GtExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "gt(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "greater_than(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -TEST_F(GtFunctionTest, LessThanValuesReturnFalse) { +TEST_F(GreaterThanFunctionTest, LessThanValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::LessThanValues()) { - EXPECT_THAT(EvaluateExpr(*GtExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "gt(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "greater_than(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -TEST_F(GtFunctionTest, GreaterThanValuesReturnTrue) { +TEST_F(GreaterThanFunctionTest, GreaterThanValuesReturnTrue) { for (const auto& pair : ComparisonValueTestData::GreaterThanValues()) { // This set includes pairs like {1.0, 1} which compare as !GreaterThan. // We expect false for those, true otherwise. @@ -697,55 +720,58 @@ TEST_F(GtFunctionTest, GreaterThanValuesReturnTrue) { std::dynamic_pointer_cast(pair.first); auto right_const = std::dynamic_pointer_cast(pair.second); - EXPECT_THAT(EvaluateExpr(*GtExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr({pair.first, pair.second})), Returns(testutil::Value(true))) - << "gt(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "greater_than(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -TEST_F(GtFunctionTest, MixedTypeValuesReturnFalse) { +TEST_F(GreaterThanFunctionTest, MixedTypeValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::MixedTypeValues()) { - EXPECT_THAT(EvaluateExpr(*GtExpr({pair.first, pair.second})), + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr({pair.first, pair.second})), Returns(testutil::Value(false))) - << "gt(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + << "greater_than(" << ExprId(pair.first) << ", " << ExprId(pair.second) + << ")"; } } -// --- Specific Gt Tests --- +// --- Specific GreaterThan Tests --- -TEST_F(GtFunctionTest, NullOperandReturnsNull) { +TEST_F(GreaterThanFunctionTest, NullOperandReturnsNull) { for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { - EXPECT_THAT( - EvaluateExpr(*GtExpr({SharedConstant(model::NullValue()), val})), - ReturnsNull()) - << "gt(null, " << ExprId(val) << ")"; - EXPECT_THAT( - EvaluateExpr(*GtExpr({val, SharedConstant(model::NullValue())})), - ReturnsNull()) - << "gt(" << ExprId(val) << ", null)"; + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr( + {SharedConstant(model::NullValue()), val})), + ReturnsNull()) + << "greater_than(null, " << ExprId(val) << ")"; + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr( + {val, SharedConstant(model::NullValue())})), + ReturnsNull()) + << "greater_than(" << ExprId(val) << ", null)"; } - EXPECT_THAT(EvaluateExpr(*GtExpr({SharedConstant(model::NullValue()), - SharedConstant(model::NullValue())})), - ReturnsNull()); EXPECT_THAT( - EvaluateExpr(*GtExpr({SharedConstant(model::NullValue()), - std::make_shared("nonexistent")})), - ReturnsError()); + EvaluateExpr(*GreaterThanExpr({SharedConstant(model::NullValue()), + SharedConstant(model::NullValue())})), + ReturnsNull()); + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr( + {SharedConstant(model::NullValue()), + std::make_shared("nonexistent")})), + ReturnsError()); } -TEST_F(GtFunctionTest, NaNComparisonsReturnFalse) { +TEST_F(GreaterThanFunctionTest, NaNComparisonsReturnFalse) { auto nan_expr = SharedConstant(std::numeric_limits::quiet_NaN()); - EXPECT_THAT(EvaluateExpr(*GtExpr({nan_expr, nan_expr})), + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr({nan_expr, nan_expr})), Returns(testutil::Value(false))); for (const auto& num_val : ComparisonValueTestData::NumericValues()) { - EXPECT_THAT(EvaluateExpr(*GtExpr({nan_expr, num_val})), + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr({nan_expr, num_val})), Returns(testutil::Value(false))) - << "gt(NaN, " << ExprId(num_val) << ")"; - EXPECT_THAT(EvaluateExpr(*GtExpr({num_val, nan_expr})), + << "greater_than(NaN, " << ExprId(num_val) << ")"; + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr({num_val, nan_expr})), Returns(testutil::Value(false))) - << "gt(" << ExprId(num_val) << ", NaN)"; + << "greater_than(" << ExprId(num_val) << ", NaN)"; } for (const auto& other_val : ComparisonValueTestData::AllSupportedComparableValues()) { @@ -757,120 +783,134 @@ TEST_F(GtFunctionTest, NaNComparisonsReturnFalse) { } } if (!is_numeric) { - EXPECT_THAT(EvaluateExpr(*GtExpr({nan_expr, other_val})), + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr({nan_expr, other_val})), Returns(testutil::Value(false))) - << "gt(NaN, " << ExprId(other_val) << ")"; - EXPECT_THAT(EvaluateExpr(*GtExpr({other_val, nan_expr})), + << "greater_than(NaN, " << ExprId(other_val) << ")"; + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr({other_val, nan_expr})), Returns(testutil::Value(false))) - << "gt(" << ExprId(other_val) << ", NaN)"; + << "greater_than(" << ExprId(other_val) << ", NaN)"; } } - EXPECT_THAT( - EvaluateExpr(*GtExpr({SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN()))), - SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN())))})), - Returns(testutil::Value(false))); + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr( + {SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN()))), + SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN())))})), + Returns(testutil::Value(false))); } -TEST_F(GtFunctionTest, ErrorHandling) { +TEST_F(GreaterThanFunctionTest, ErrorHandling) { auto error_expr = std::make_shared("a.b"); auto non_map_input = testutil::Doc("coll/doc", 1, testutil::Map("a", 123)); for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { - EXPECT_THAT(EvaluateExpr(*GtExpr({error_expr, val}), non_map_input), - ReturnsError()); - EXPECT_THAT(EvaluateExpr(*GtExpr({val, error_expr}), non_map_input), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*GreaterThanExpr({error_expr, val}), non_map_input), + ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*GreaterThanExpr({val, error_expr}), non_map_input), + ReturnsError()); } - EXPECT_THAT(EvaluateExpr(*GtExpr({error_expr, error_expr}), non_map_input), - ReturnsError()); EXPECT_THAT( - EvaluateExpr(*GtExpr({error_expr, SharedConstant(model::NullValue())}), - non_map_input), + EvaluateExpr(*GreaterThanExpr({error_expr, error_expr}), non_map_input), + ReturnsError()); + EXPECT_THAT( + EvaluateExpr( + *GreaterThanExpr({error_expr, SharedConstant(model::NullValue())}), + non_map_input), ReturnsError()); } -TEST_F(GtFunctionTest, MissingFieldReturnsError) { - EXPECT_THAT(EvaluateExpr(*GtExpr({std::make_shared("nonexistent"), +TEST_F(GreaterThanFunctionTest, MissingFieldReturnsError) { + EXPECT_THAT(EvaluateExpr( + *GreaterThanExpr({std::make_shared("nonexistent"), SharedConstant(testutil::Value(1LL))})), ReturnsError()); - EXPECT_THAT( - EvaluateExpr(*GtExpr({SharedConstant(testutil::Value(1LL)), - std::make_shared("nonexistent")})), - ReturnsError()); + EXPECT_THAT(EvaluateExpr(*GreaterThanExpr( + {SharedConstant(testutil::Value(1LL)), + std::make_shared("nonexistent")})), + ReturnsError()); } -// --- Gte (>=) Tests --- +// --- GreaterThanOrEqual (>=) Tests --- -TEST_F(GteFunctionTest, EquivalentValuesReturnTrue) { +TEST_F(GreaterThanOrEqualFunctionTest, EquivalentValuesReturnTrue) { for (const auto& pair : ComparisonValueTestData::EquivalentValues()) { - EXPECT_THAT(EvaluateExpr(*GteExpr({pair.first, pair.second})), - Returns(testutil::Value(true))) - << "gte(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + EXPECT_THAT( + EvaluateExpr(*GreaterThanOrEqualExpr({pair.first, pair.second})), + Returns(testutil::Value(true))) + << "greater_than_or_equal(" << ExprId(pair.first) << ", " + << ExprId(pair.second) << ")"; } } -TEST_F(GteFunctionTest, LessThanValuesReturnFalse) { +TEST_F(GreaterThanOrEqualFunctionTest, LessThanValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::LessThanValues()) { - EXPECT_THAT(EvaluateExpr(*GteExpr({pair.first, pair.second})), - Returns(testutil::Value(false))) - << "gte(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + EXPECT_THAT( + EvaluateExpr(*GreaterThanOrEqualExpr({pair.first, pair.second})), + Returns(testutil::Value(false))) + << "greater_than_or_equal(" << ExprId(pair.first) << ", " + << ExprId(pair.second) << ")"; } } -TEST_F(GteFunctionTest, GreaterThanValuesReturnTrue) { +TEST_F(GreaterThanOrEqualFunctionTest, GreaterThanValuesReturnTrue) { for (const auto& pair : ComparisonValueTestData::GreaterThanValues()) { - EXPECT_THAT(EvaluateExpr(*GteExpr({pair.first, pair.second})), - Returns(testutil::Value(true))) - << "gte(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + EXPECT_THAT( + EvaluateExpr(*GreaterThanOrEqualExpr({pair.first, pair.second})), + Returns(testutil::Value(true))) + << "greater_than_or_equal(" << ExprId(pair.first) << ", " + << ExprId(pair.second) << ")"; } } -TEST_F(GteFunctionTest, MixedTypeValuesReturnFalse) { +TEST_F(GreaterThanOrEqualFunctionTest, MixedTypeValuesReturnFalse) { for (const auto& pair : ComparisonValueTestData::MixedTypeValues()) { - EXPECT_THAT(EvaluateExpr(*GteExpr({pair.first, pair.second})), - Returns(testutil::Value(false))) - << "gte(" << ExprId(pair.first) << ", " << ExprId(pair.second) << ")"; + EXPECT_THAT( + EvaluateExpr(*GreaterThanOrEqualExpr({pair.first, pair.second})), + Returns(testutil::Value(false))) + << "greater_than_or_equal(" << ExprId(pair.first) << ", " + << ExprId(pair.second) << ")"; } } -// --- Specific Gte Tests --- +// --- Specific GreaterThanOrEqual Tests --- -TEST_F(GteFunctionTest, NullOperandReturnsNull) { +TEST_F(GreaterThanOrEqualFunctionTest, NullOperandReturnsNull) { for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { - EXPECT_THAT( - EvaluateExpr(*GteExpr({SharedConstant(model::NullValue()), val})), - ReturnsNull()) - << "gte(null, " << ExprId(val) << ")"; - EXPECT_THAT( - EvaluateExpr(*GteExpr({val, SharedConstant(model::NullValue())})), - ReturnsNull()) - << "gte(" << ExprId(val) << ", null)"; - } - EXPECT_THAT(EvaluateExpr(*GteExpr({SharedConstant(model::NullValue()), - SharedConstant(model::NullValue())})), + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr( + {SharedConstant(model::NullValue()), val})), + ReturnsNull()) + << "greater_than_or_equal(null, " << ExprId(val) << ")"; + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr( + {val, SharedConstant(model::NullValue())})), + ReturnsNull()) + << "greater_than_or_equal(" << ExprId(val) << ", null)"; + } + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr( + {SharedConstant(model::NullValue()), + SharedConstant(model::NullValue())})), ReturnsNull()); - EXPECT_THAT( - EvaluateExpr(*GteExpr({SharedConstant(model::NullValue()), - std::make_shared("nonexistent")})), - ReturnsError()); + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr( + {SharedConstant(model::NullValue()), + std::make_shared("nonexistent")})), + ReturnsError()); } -TEST_F(GteFunctionTest, NaNComparisonsReturnFalse) { +TEST_F(GreaterThanOrEqualFunctionTest, NaNComparisonsReturnFalse) { auto nan_expr = SharedConstant(std::numeric_limits::quiet_NaN()); - EXPECT_THAT(EvaluateExpr(*GteExpr({nan_expr, nan_expr})), + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr({nan_expr, nan_expr})), Returns(testutil::Value(false))); for (const auto& num_val : ComparisonValueTestData::NumericValues()) { - EXPECT_THAT(EvaluateExpr(*GteExpr({nan_expr, num_val})), + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr({nan_expr, num_val})), Returns(testutil::Value(false))) - << "gte(NaN, " << ExprId(num_val) << ")"; - EXPECT_THAT(EvaluateExpr(*GteExpr({num_val, nan_expr})), + << "greater_than_or_equal(NaN, " << ExprId(num_val) << ")"; + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr({num_val, nan_expr})), Returns(testutil::Value(false))) - << "gte(" << ExprId(num_val) << ", NaN)"; + << "greater_than_or_equal(" << ExprId(num_val) << ", NaN)"; } for (const auto& other_val : ComparisonValueTestData::AllSupportedComparableValues()) { @@ -882,50 +922,54 @@ TEST_F(GteFunctionTest, NaNComparisonsReturnFalse) { } } if (!is_numeric) { - EXPECT_THAT(EvaluateExpr(*GteExpr({nan_expr, other_val})), + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr({nan_expr, other_val})), Returns(testutil::Value(false))) - << "gte(NaN, " << ExprId(other_val) << ")"; - EXPECT_THAT(EvaluateExpr(*GteExpr({other_val, nan_expr})), + << "greater_than_or_equal(NaN, " << ExprId(other_val) << ")"; + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr({other_val, nan_expr})), Returns(testutil::Value(false))) - << "gte(" << ExprId(other_val) << ", NaN)"; + << "greater_than_or_equal(" << ExprId(other_val) << ", NaN)"; } } - EXPECT_THAT( - EvaluateExpr(*GteExpr({SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN()))), - SharedConstant(testutil::Array(testutil::Value( - std::numeric_limits::quiet_NaN())))})), - Returns(testutil::Value(false))); + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr( + {SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN()))), + SharedConstant(testutil::Array(testutil::Value( + std::numeric_limits::quiet_NaN())))})), + Returns(testutil::Value(false))); } -TEST_F(GteFunctionTest, ErrorHandling) { +TEST_F(GreaterThanOrEqualFunctionTest, ErrorHandling) { auto error_expr = std::make_shared("a.b"); auto non_map_input = testutil::Doc("coll/doc", 1, testutil::Map("a", 123)); for (const auto& val : ComparisonValueTestData::AllSupportedComparableValues()) { - EXPECT_THAT(EvaluateExpr(*GteExpr({error_expr, val}), non_map_input), - ReturnsError()); - EXPECT_THAT(EvaluateExpr(*GteExpr({val, error_expr}), non_map_input), - ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*GreaterThanOrEqualExpr({error_expr, val}), non_map_input), + ReturnsError()); + EXPECT_THAT( + EvaluateExpr(*GreaterThanOrEqualExpr({val, error_expr}), non_map_input), + ReturnsError()); } - EXPECT_THAT(EvaluateExpr(*GteExpr({error_expr, error_expr}), non_map_input), + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr({error_expr, error_expr}), + non_map_input), ReturnsError()); EXPECT_THAT( - EvaluateExpr(*GteExpr({error_expr, SharedConstant(model::NullValue())}), + EvaluateExpr(*GreaterThanOrEqualExpr( + {error_expr, SharedConstant(model::NullValue())}), non_map_input), ReturnsError()); } -TEST_F(GteFunctionTest, MissingFieldReturnsError) { - EXPECT_THAT( - EvaluateExpr(*GteExpr({std::make_shared("nonexistent"), - SharedConstant(testutil::Value(1LL))})), - ReturnsError()); - EXPECT_THAT( - EvaluateExpr(*GteExpr({SharedConstant(testutil::Value(1LL)), - std::make_shared("nonexistent")})), - ReturnsError()); +TEST_F(GreaterThanOrEqualFunctionTest, MissingFieldReturnsError) { + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr( + {std::make_shared("nonexistent"), + SharedConstant(testutil::Value(1LL))})), + ReturnsError()); + EXPECT_THAT(EvaluateExpr(*GreaterThanOrEqualExpr( + {SharedConstant(testutil::Value(1LL)), + std::make_shared("nonexistent")})), + ReturnsError()); } } // namespace core diff --git a/Firestore/core/test/unit/core/expressions/logical_test.cc b/Firestore/core/test/unit/core/expressions/logical_test.cc index 81633e2c106..73f3d10c4d9 100644 --- a/Firestore/core/test/unit/core/expressions/logical_test.cc +++ b/Firestore/core/test/unit/core/expressions/logical_test.cc @@ -50,9 +50,9 @@ using testutil::IsNanExpr; using testutil::IsNotNanExpr; using testutil::IsNotNullExpr; using testutil::IsNullExpr; -using testutil::LogicalMaxExpr; -using testutil::LogicalMinExpr; using testutil::Map; +using testutil::MaximumExpr; +using testutil::MinimumExpr; using testutil::NotExpr; using testutil::OrExpr; using testutil::Returns; @@ -507,143 +507,141 @@ TEST_F(IsNanFunctionTest, NonNumericReturnsError) { ReturnsError()); } -// --- LogicalMaximum Tests --- -class LogicalMaximumFunctionTest : public LogicalExpressionsTest {}; +// --- Maximum Tests --- +class MaximumFunctionTest : public LogicalExpressionsTest {}; -TEST_F(LogicalMaximumFunctionTest, NumericType) { - auto expr = testutil::LogicalMaxExpr( +TEST_F(MaximumFunctionTest, NumericType) { + auto expr = testutil::MaximumExpr( {SharedConstant(Value(1LL)), - testutil::LogicalMaxExpr( + testutil::MaximumExpr( {SharedConstant(Value(2.0)), SharedConstant(Value(3LL))})}); EXPECT_THAT(EvaluateExpr(*expr), Returns(Value(3LL))); // Max(1, Max(2.0, 3)) -> 3 } -TEST_F(LogicalMaximumFunctionTest, StringType) { - auto expr = testutil::LogicalMaxExpr( - {testutil::LogicalMaxExpr( +TEST_F(MaximumFunctionTest, StringType) { + auto expr = testutil::MaximumExpr( + {testutil::MaximumExpr( {SharedConstant(Value("a")), SharedConstant(Value("b"))}), SharedConstant(Value("c"))}); EXPECT_THAT(EvaluateExpr(*expr), Returns(Value("c"))); // Max(Max("a", "b"), "c") -> "c" } -TEST_F(LogicalMaximumFunctionTest, MixedType) { +TEST_F(MaximumFunctionTest, MixedType) { // Type order: Null < Bool < Number < Timestamp < String < Blob < Ref < // GeoPoint < Array < Map - auto expr = testutil::LogicalMaxExpr( + auto expr = testutil::MaximumExpr( {SharedConstant(Value(1LL)), - testutil::LogicalMaxExpr( + testutil::MaximumExpr( {SharedConstant(Value("1")), SharedConstant(Value(0LL))})}); EXPECT_THAT( EvaluateExpr(*expr), Returns(Value("1"))); // Max(1, Max("1", 0)) -> "1" (String > Number) } -TEST_F(LogicalMaximumFunctionTest, OnlyNullAndErrorReturnsNull) { - auto expr = testutil::LogicalMaxExpr({NullExpr, ErrorExpr()}); +TEST_F(MaximumFunctionTest, OnlyNullAndErrorReturnsNull) { + auto expr = testutil::MaximumExpr({NullExpr, ErrorExpr()}); EXPECT_THAT(EvaluateExpr(*expr, error_doc_), ReturnsNull()); } -TEST_F(LogicalMaximumFunctionTest, NanAndNumbers) { +TEST_F(MaximumFunctionTest, NanAndNumbers) { // NaN is handled specially; it's skipped unless it's the only non-null/error // value. - auto expr = testutil::LogicalMaxExpr({NanExpr, SharedConstant(Value(0LL))}); + auto expr = testutil::MaximumExpr({NanExpr, SharedConstant(Value(0LL))}); EXPECT_THAT(EvaluateExpr(*expr), Returns(Value(0LL))); // Max(NaN, 0) -> 0 - auto expr2 = testutil::LogicalMaxExpr({SharedConstant(Value(0LL)), NanExpr}); + auto expr2 = testutil::MaximumExpr({SharedConstant(Value(0LL)), NanExpr}); EXPECT_THAT(EvaluateExpr(*expr2), Returns(Value(0LL))); // Max(0, NaN) -> 0 - auto expr3 = testutil::LogicalMaxExpr({NanExpr, NullExpr, ErrorExpr()}); + auto expr3 = testutil::MaximumExpr({NanExpr, NullExpr, ErrorExpr()}); EXPECT_THAT(EvaluateExpr(*expr3, error_doc_), Returns(Value(NAN))); // Max(NaN, Null, Error) -> NaN - auto expr4 = testutil::LogicalMaxExpr({NanExpr, ErrorExpr()}); + auto expr4 = testutil::MaximumExpr({NanExpr, ErrorExpr()}); EXPECT_THAT(EvaluateExpr(*expr4, error_doc_), Returns(Value(NAN))); // Max(NaN, Error) -> NaN } -TEST_F(LogicalMaximumFunctionTest, ErrorInputSkip) { - auto expr = - testutil::LogicalMaxExpr({ErrorExpr(), SharedConstant(Value(1LL))}); +TEST_F(MaximumFunctionTest, ErrorInputSkip) { + auto expr = testutil::MaximumExpr({ErrorExpr(), SharedConstant(Value(1LL))}); EXPECT_THAT(EvaluateExpr(*expr, error_doc_), Returns(Value(1LL))); } -TEST_F(LogicalMaximumFunctionTest, NullInputSkip) { - auto expr = testutil::LogicalMaxExpr({NullExpr, SharedConstant(Value(1LL))}); +TEST_F(MaximumFunctionTest, NullInputSkip) { + auto expr = testutil::MaximumExpr({NullExpr, SharedConstant(Value(1LL))}); EXPECT_THAT(EvaluateExpr(*expr), Returns(Value(1LL))); } -TEST_F(LogicalMaximumFunctionTest, EquivalentNumerics) { - auto expr = testutil::LogicalMaxExpr( +TEST_F(MaximumFunctionTest, EquivalentNumerics) { + auto expr = testutil::MaximumExpr( {SharedConstant(Value(1LL)), SharedConstant(Value(1.0))}); // Max(1, 1.0) -> 1 (or 1.0, they are equivalent, result depends on internal // order) Let's check if it's equivalent to 1LL EXPECT_THAT(EvaluateExpr(*expr), Returns(Value(1LL))); } -// --- LogicalMinimum Tests --- -class LogicalMinimumFunctionTest : public LogicalExpressionsTest {}; +// --- Minimum Tests --- +class MinimumFunctionTest : public LogicalExpressionsTest {}; -TEST_F(LogicalMinimumFunctionTest, NumericType) { - auto expr = testutil::LogicalMinExpr( +TEST_F(MinimumFunctionTest, NumericType) { + auto expr = testutil::MinimumExpr( {SharedConstant(Value(1LL)), - testutil::LogicalMinExpr( + testutil::MinimumExpr( {SharedConstant(Value(2.0)), SharedConstant(Value(3LL))})}); EXPECT_THAT(EvaluateExpr(*expr), Returns(Value(1LL))); // Min(1, Min(2.0, 3)) -> 1 } -TEST_F(LogicalMinimumFunctionTest, StringType) { - auto expr = testutil::LogicalMinExpr( - {testutil::LogicalMinExpr( +TEST_F(MinimumFunctionTest, StringType) { + auto expr = testutil::MinimumExpr( + {testutil::MinimumExpr( {SharedConstant(Value("a")), SharedConstant(Value("b"))}), SharedConstant(Value("c"))}); EXPECT_THAT(EvaluateExpr(*expr), Returns(Value("a"))); // Min(Min("a", "b"), "c") -> "a" } -TEST_F(LogicalMinimumFunctionTest, MixedType) { +TEST_F(MinimumFunctionTest, MixedType) { // Type order: Null < Bool < Number < Timestamp < String < Blob < Ref < // GeoPoint < Array < Map - auto expr = testutil::LogicalMinExpr( + auto expr = testutil::MinimumExpr( {SharedConstant(Value(1LL)), - testutil::LogicalMinExpr( + testutil::MinimumExpr( {SharedConstant(Value("1")), SharedConstant(Value(0LL))})}); EXPECT_THAT( EvaluateExpr(*expr), Returns(Value(0LL))); // Min(1, Min("1", 0)) -> 0 (Number < String) } -TEST_F(LogicalMinimumFunctionTest, OnlyNullAndErrorReturnsNull) { - auto expr = testutil::LogicalMinExpr({NullExpr, ErrorExpr()}); +TEST_F(MinimumFunctionTest, OnlyNullAndErrorReturnsNull) { + auto expr = testutil::MinimumExpr({NullExpr, ErrorExpr()}); EXPECT_THAT(EvaluateExpr(*expr, error_doc_), ReturnsNull()); } -TEST_F(LogicalMinimumFunctionTest, NanAndNumbers) { +TEST_F(MinimumFunctionTest, NanAndNumbers) { // NaN is handled specially; it's considered the minimum unless skipped. - auto expr = testutil::LogicalMinExpr({NanExpr, SharedConstant(Value(0LL))}); + auto expr = testutil::MinimumExpr({NanExpr, SharedConstant(Value(0LL))}); EXPECT_THAT(EvaluateExpr(*expr), Returns(Value(NAN))); // Min(NaN, 0) -> NaN - auto expr2 = testutil::LogicalMinExpr({SharedConstant(Value(0LL)), NanExpr}); + auto expr2 = testutil::MinimumExpr({SharedConstant(Value(0LL)), NanExpr}); EXPECT_THAT(EvaluateExpr(*expr2), Returns(Value(NAN))); // Min(0, NaN) -> NaN - auto expr3 = testutil::LogicalMinExpr({NanExpr, NullExpr, ErrorExpr()}); + auto expr3 = testutil::MinimumExpr({NanExpr, NullExpr, ErrorExpr()}); EXPECT_THAT(EvaluateExpr(*expr3, error_doc_), Returns(Value(NAN))); // Min(NaN, Null, Error) -> NaN - auto expr4 = testutil::LogicalMinExpr({NanExpr, ErrorExpr()}); + auto expr4 = testutil::MinimumExpr({NanExpr, ErrorExpr()}); EXPECT_THAT(EvaluateExpr(*expr4, error_doc_), Returns(Value(NAN))); // Min(NaN, Error) -> NaN } -TEST_F(LogicalMinimumFunctionTest, ErrorInputSkip) { - auto expr = - testutil::LogicalMinExpr({ErrorExpr(), SharedConstant(Value(1LL))}); +TEST_F(MinimumFunctionTest, ErrorInputSkip) { + auto expr = testutil::MinimumExpr({ErrorExpr(), SharedConstant(Value(1LL))}); EXPECT_THAT(EvaluateExpr(*expr, error_doc_), Returns(Value(1LL))); } -TEST_F(LogicalMinimumFunctionTest, NullInputSkip) { - auto expr = testutil::LogicalMinExpr({NullExpr, SharedConstant(Value(1LL))}); +TEST_F(MinimumFunctionTest, NullInputSkip) { + auto expr = testutil::MinimumExpr({NullExpr, SharedConstant(Value(1LL))}); EXPECT_THAT(EvaluateExpr(*expr), Returns(Value(1LL))); } -TEST_F(LogicalMinimumFunctionTest, EquivalentNumerics) { - auto expr = testutil::LogicalMinExpr( +TEST_F(MinimumFunctionTest, EquivalentNumerics) { + auto expr = testutil::MinimumExpr( {SharedConstant(Value(1LL)), SharedConstant(Value(1.0))}); // Min(1, 1.0) -> 1 (or 1.0, they are equivalent) EXPECT_THAT(EvaluateExpr(*expr), Returns(Value(1LL))); @@ -653,16 +651,16 @@ TEST_F(LogicalMinimumFunctionTest, EquivalentNumerics) { class NotFunctionTest : public LogicalExpressionsTest {}; TEST_F(NotFunctionTest, TrueToFalse) { - // Using EqExpr from comparison_test helpers for simplicity - auto true_cond = testutil::EqExpr( + // Using EqualExpr from comparison_test helpers for simplicity + auto true_cond = testutil::EqualExpr( {SharedConstant(Value(1LL)), SharedConstant(Value(1LL))}); EXPECT_THAT(EvaluateExpr(*testutil::NotExpr(true_cond)), Returns(Value(false))); } TEST_F(NotFunctionTest, FalseToTrue) { - // Using NeqExpr from comparison_test helpers for simplicity - auto false_cond = testutil::NeqExpr( + // Using NotEqualExpr from comparison_test helpers for simplicity + auto false_cond = testutil::NotEqualExpr( {SharedConstant(Value(1LL)), SharedConstant(Value(1LL))}); EXPECT_THAT(EvaluateExpr(*testutil::NotExpr(false_cond)), Returns(Value(true))); diff --git a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc index e84c450a512..3a46b01514a 100644 --- a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc +++ b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc @@ -49,29 +49,29 @@ using testutil::CharLengthExpr; using testutil::DivideExpr; using testutil::EndsWithExpr; using testutil::EqAnyExpr; -using testutil::EqExpr; +using testutil::EqualExpr; using testutil::EvaluateExpr; -using testutil::GteExpr; -using testutil::GtExpr; +using testutil::GreaterThanExpr; +using testutil::GreaterThanOrEqualExpr; using testutil::IsNanExpr; using testutil::IsNotNanExpr; +using testutil::LessThanExpr; +using testutil::LessThanOrEqualExpr; using testutil::LikeExpr; -using testutil::LteExpr; -using testutil::LtExpr; using testutil::ModExpr; using testutil::MultiplyExpr; -using testutil::NeqExpr; using testutil::NotEqAnyExpr; +using testutil::NotEqualExpr; using testutil::RegexContainsExpr; using testutil::RegexMatchExpr; using testutil::Returns; using testutil::ReturnsError; using testutil::ReturnsNull; -using testutil::ReverseExpr; using testutil::SharedConstant; using testutil::StartsWithExpr; -using testutil::StrConcatExpr; -using testutil::StrContainsExpr; +using testutil::StringConcatExpr; +using testutil::StringContainsExpr; +using testutil::StringReverseExpr; using testutil::SubtractExpr; using testutil::TimestampToUnixMicrosExpr; using testutil::TimestampToUnixMillisExpr; @@ -112,7 +112,7 @@ TEST_F(MirroringSemanticsTest, UnaryFunctionInputMirroring) { [](auto v) { return IsNanExpr(v); }, [](auto v) { return IsNotNanExpr(v); }, [](auto v) { return ArrayLengthExpr(v); }, - [](auto v) { return ReverseExpr(v); }, + [](auto v) { return StringReverseExpr(v); }, [](auto v) { return CharLengthExpr(v); }, [](auto v) { return ByteLengthExpr(v); }, [](auto v) { return ToLowerExpr(v); }, @@ -162,7 +162,7 @@ TEST_F(MirroringSemanticsTest, BinaryFunctionInputMirroring) { using BinaryBuilder = std::function( std::shared_ptr, std::shared_ptr)>; - // Note: Variadic functions like add, multiply, str_concat are tested + // Note: Variadic functions like add, multiply, string_concat are tested // with their base binary case here. const std::vector binary_function_builders = { // Arithmetic (Variadic, base is binary) @@ -172,12 +172,12 @@ TEST_F(MirroringSemanticsTest, BinaryFunctionInputMirroring) { [](auto v1, auto v2) { return DivideExpr({v1, v2}); }, [](auto v1, auto v2) { return ModExpr({v1, v2}); }, // Comparison - [](auto v1, auto v2) { return EqExpr({v1, v2}); }, - [](auto v1, auto v2) { return NeqExpr({v1, v2}); }, - [](auto v1, auto v2) { return LtExpr({v1, v2}); }, - [](auto v1, auto v2) { return LteExpr({v1, v2}); }, - [](auto v1, auto v2) { return GtExpr({v1, v2}); }, - [](auto v1, auto v2) { return GteExpr({v1, v2}); }, + [](auto v1, auto v2) { return EqualExpr({v1, v2}); }, + [](auto v1, auto v2) { return NotEqualExpr({v1, v2}); }, + [](auto v1, auto v2) { return LessThanExpr({v1, v2}); }, + [](auto v1, auto v2) { return LessThanOrEqualExpr({v1, v2}); }, + [](auto v1, auto v2) { return GreaterThanExpr({v1, v2}); }, + [](auto v1, auto v2) { return GreaterThanOrEqualExpr({v1, v2}); }, // Array [](auto v1, auto v2) { return ArrayContainsExpr({v1, v2}); }, [](auto v1, auto v2) { return ArrayContainsAllExpr({v1, v2}); }, @@ -188,10 +188,10 @@ TEST_F(MirroringSemanticsTest, BinaryFunctionInputMirroring) { [](auto v1, auto v2) { return LikeExpr(v1, v2); }, [](auto v1, auto v2) { return RegexContainsExpr(v1, v2); }, [](auto v1, auto v2) { return RegexMatchExpr(v1, v2); }, - [](auto v1, auto v2) { return StrContainsExpr(v1, v2); }, + [](auto v1, auto v2) { return StringContainsExpr(v1, v2); }, [](auto v1, auto v2) { return StartsWithExpr(v1, v2); }, [](auto v1, auto v2) { return EndsWithExpr(v1, v2); }, - [](auto v1, auto v2) { return StrConcatExpr({v1, v2}); } + [](auto v1, auto v2) { return StringConcatExpr({v1, v2}); } // TODO(b/351084804): mapGet is not implemented yet }; diff --git a/Firestore/core/test/unit/core/expressions/string_test.cc b/Firestore/core/test/unit/core/expressions/string_test.cc index 404f9f1eb0a..dba96829ec1 100644 --- a/Firestore/core/test/unit/core/expressions/string_test.cc +++ b/Firestore/core/test/unit/core/expressions/string_test.cc @@ -46,11 +46,11 @@ using testutil::RegexMatchExpr; using testutil::Returns; using testutil::ReturnsError; using testutil::ReturnsNull; // If needed for string functions -using testutil::ReverseExpr; using testutil::SharedConstant; using testutil::StartsWithExpr; -using testutil::StrConcatExpr; -using testutil::StrContainsExpr; +using testutil::StringConcatExpr; +using testutil::StringContainsExpr; +using testutil::StringReverseExpr; using testutil::ToLowerExpr; using testutil::ToUpperExpr; using testutil::TrimExpr; @@ -69,7 +69,7 @@ class StrContainsTest : public ::testing::Test {}; class ToLowerTest : public ::testing::Test {}; class ToUpperTest : public ::testing::Test {}; class TrimTest : public ::testing::Test {}; -class ReverseTest : public ::testing::Test {}; +class StringReverseTest : public ::testing::Test {}; // --- ByteLength Tests --- TEST_F(ByteLengthTest, EmptyString) { @@ -346,21 +346,21 @@ TEST_F(CharLengthTest, LargeString) { // --- StrConcat Tests --- TEST_F(StrConcatTest, MultipleStringChildrenReturnsCombination) { EXPECT_THAT( - EvaluateExpr(*StrConcatExpr( + EvaluateExpr(*StringConcatExpr( {SharedConstant("foo"), SharedConstant(" "), SharedConstant("bar")})), Returns(Value("foo bar"))); } TEST_F(StrConcatTest, MultipleNonStringChildrenReturnsError) { EXPECT_THAT( - EvaluateExpr(*StrConcatExpr({SharedConstant("foo"), - SharedConstant(static_cast(42LL)), - SharedConstant("bar")})), + EvaluateExpr(*StringConcatExpr( + {SharedConstant("foo"), SharedConstant(static_cast(42LL)), + SharedConstant("bar")})), ReturnsError()); } TEST_F(StrConcatTest, MultipleCalls) { - auto func = StrConcatExpr( + auto func = StringConcatExpr( {SharedConstant("foo"), SharedConstant(" "), SharedConstant("bar")}); EXPECT_THAT(EvaluateExpr(*func), Returns(Value("foo bar"))); EXPECT_THAT(EvaluateExpr(*func), @@ -377,7 +377,7 @@ TEST_F(StrConcatTest, LargeNumberOfInputs) { expected_result += "a"; } // Need to construct FunctionExpr with vector directly - auto func = StrConcatExpr(std::move(args)); + auto func = StringConcatExpr(std::move(args)); EXPECT_THAT(EvaluateExpr(*func), Returns(Value(expected_result))); } @@ -386,9 +386,9 @@ TEST_F(StrConcatTest, LargeStrings) { std::string b500(500, 'b'); std::string c500(500, 'c'); // Use .c_str() for std::string variables - auto func = - StrConcatExpr({SharedConstant(a500.c_str()), SharedConstant(b500.c_str()), - SharedConstant(c500.c_str())}); + auto func = StringConcatExpr({SharedConstant(a500.c_str()), + SharedConstant(b500.c_str()), + SharedConstant(c500.c_str())}); EXPECT_THAT(EvaluateExpr(*func), Returns(Value(a500 + b500 + c500))); } @@ -678,51 +678,51 @@ TEST_F(StartsWithTest, GetLargePrefixReturnsFalse) { // --- StrContains Tests --- TEST_F(StrContainsTest, ValueNonStringIsError) { EXPECT_THAT( - EvaluateExpr(*StrContainsExpr(SharedConstant(static_cast(42LL)), - SharedConstant("value"))), + EvaluateExpr(*StringContainsExpr( + SharedConstant(static_cast(42LL)), SharedConstant("value"))), ReturnsError()); } TEST_F(StrContainsTest, SubStringNonStringIsError) { - EXPECT_THAT(EvaluateExpr( - *StrContainsExpr(SharedConstant("search space"), - SharedConstant(static_cast(42LL)))), + EXPECT_THAT(EvaluateExpr(*StringContainsExpr( + SharedConstant("search space"), + SharedConstant(static_cast(42LL)))), ReturnsError()); } TEST_F(StrContainsTest, ExecuteTrue) { - EXPECT_THAT(EvaluateExpr( - *StrContainsExpr(SharedConstant("abc"), SharedConstant("c"))), + EXPECT_THAT(EvaluateExpr(*StringContainsExpr(SharedConstant("abc"), + SharedConstant("c"))), Returns(Value(true))); - EXPECT_THAT(EvaluateExpr(*StrContainsExpr(SharedConstant("abc"), - SharedConstant("bc"))), + EXPECT_THAT(EvaluateExpr(*StringContainsExpr(SharedConstant("abc"), + SharedConstant("bc"))), Returns(Value(true))); - EXPECT_THAT(EvaluateExpr(*StrContainsExpr(SharedConstant("abc"), - SharedConstant("abc"))), + EXPECT_THAT(EvaluateExpr(*StringContainsExpr(SharedConstant("abc"), + SharedConstant("abc"))), + Returns(Value(true))); + EXPECT_THAT(EvaluateExpr(*StringContainsExpr(SharedConstant("abc"), + SharedConstant(""))), Returns(Value(true))); EXPECT_THAT( - EvaluateExpr(*StrContainsExpr(SharedConstant("abc"), SharedConstant(""))), - Returns(Value(true))); - EXPECT_THAT( - EvaluateExpr(*StrContainsExpr(SharedConstant(""), SharedConstant(""))), + EvaluateExpr(*StringContainsExpr(SharedConstant(""), SharedConstant(""))), Returns(Value(true))); - EXPECT_THAT(EvaluateExpr( - *StrContainsExpr(SharedConstant("☃☃☃"), SharedConstant("☃"))), + EXPECT_THAT(EvaluateExpr(*StringContainsExpr(SharedConstant("☃☃☃"), + SharedConstant("☃"))), Returns(Value(true))); } TEST_F(StrContainsTest, ExecuteFalse) { - EXPECT_THAT(EvaluateExpr(*StrContainsExpr(SharedConstant("abc"), - SharedConstant("abcd"))), + EXPECT_THAT(EvaluateExpr(*StringContainsExpr(SharedConstant("abc"), + SharedConstant("abcd"))), + Returns(Value(false))); + EXPECT_THAT(EvaluateExpr(*StringContainsExpr(SharedConstant("abc"), + SharedConstant("d"))), Returns(Value(false))); EXPECT_THAT(EvaluateExpr( - *StrContainsExpr(SharedConstant("abc"), SharedConstant("d"))), + *StringContainsExpr(SharedConstant(""), SharedConstant("a"))), Returns(Value(false))); - EXPECT_THAT( - EvaluateExpr(*StrContainsExpr(SharedConstant(""), SharedConstant("a"))), - Returns(Value(false))); - EXPECT_THAT(EvaluateExpr(*StrContainsExpr(SharedConstant(""), - SharedConstant("abcde"))), + EXPECT_THAT(EvaluateExpr(*StringContainsExpr(SharedConstant(""), + SharedConstant("abcde"))), Returns(Value(false))); } @@ -800,30 +800,30 @@ TEST_F(TrimTest, Null) { EXPECT_THAT(EvaluateExpr(*TrimExpr(SharedConstant(nullptr))), ReturnsNull()); } -// --- Reverse Tests --- -TEST_F(ReverseTest, Basic) { - EXPECT_THAT(EvaluateExpr(*ReverseExpr(SharedConstant("abc"))), +// --- StringReverse Tests --- +TEST_F(StringReverseTest, Basic) { + EXPECT_THAT(EvaluateExpr(*StringReverseExpr(SharedConstant("abc"))), Returns(Value("cba"))); } -TEST_F(ReverseTest, Empty) { - EXPECT_THAT(EvaluateExpr(*ReverseExpr(SharedConstant(""))), +TEST_F(StringReverseTest, Empty) { + EXPECT_THAT(EvaluateExpr(*StringReverseExpr(SharedConstant(""))), Returns(Value(""))); } -TEST_F(ReverseTest, Unicode) { - EXPECT_THAT(EvaluateExpr(*ReverseExpr(SharedConstant("aé好🂡"))), +TEST_F(StringReverseTest, Unicode) { + EXPECT_THAT(EvaluateExpr(*StringReverseExpr(SharedConstant("aé好🂡"))), Returns(Value("🂡好éa"))); } -TEST_F(ReverseTest, NonString) { - EXPECT_THAT( - EvaluateExpr(*ReverseExpr(SharedConstant(static_cast(123LL)))), - ReturnsError()); +TEST_F(StringReverseTest, NonString) { + EXPECT_THAT(EvaluateExpr(*StringReverseExpr( + SharedConstant(static_cast(123LL)))), + ReturnsError()); } -TEST_F(ReverseTest, Null) { - EXPECT_THAT(EvaluateExpr(*ReverseExpr(SharedConstant(nullptr))), +TEST_F(StringReverseTest, Null) { + EXPECT_THAT(EvaluateExpr(*StringReverseExpr(SharedConstant(nullptr))), ReturnsNull()); } diff --git a/Firestore/core/test/unit/core/pipeline/canonify_eq_test.cc b/Firestore/core/test/unit/core/pipeline/canonify_eq_test.cc index 7a8f4caab57..1b4f4fd7124 100644 --- a/Firestore/core/test/unit/core/pipeline/canonify_eq_test.cc +++ b/Firestore/core/test/unit/core/pipeline/canonify_eq_test.cc @@ -71,7 +71,7 @@ using testutil::SharedConstant; using testutil::Value; // Expression helpers using testutil::EqAnyExpr; -using testutil::EqExpr; +using testutil::EqualExpr; // Helper to get canonical ID directly for RealtimePipeline std::string GetPipelineCanonicalId(const RealtimePipeline& pipeline) { @@ -119,7 +119,7 @@ class CanonifyEqPipelineTest : public ::testing::Test { TEST_F(CanonifyEqPipelineTest, CanonifySimpleWhere) { RealtimePipeline p = StartPipeline("test"); - p = p.AddingStage(std::make_shared(EqExpr( + p = p.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Value(42LL))}))); EXPECT_EQ(GetPipelineCanonicalId(p), @@ -129,7 +129,7 @@ TEST_F(CanonifyEqPipelineTest, CanonifySimpleWhere) { TEST_F(CanonifyEqPipelineTest, CanonifyMultipleStages) { RealtimePipeline p = StartPipeline("test"); - p = p.AddingStage(std::make_shared(EqExpr( + p = p.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Value(42LL))}))); p = p.AddingStage(std::make_shared(10)); p = p.AddingStage(std::make_shared( @@ -239,11 +239,11 @@ TEST_F(CanonifyEqPipelineTest, CanonifyCollectionGroupSource) { TEST_F(CanonifyEqPipelineTest, EqReturnsTrueForIdenticalPipelines) { RealtimePipeline p1 = StartPipeline("test"); - p1 = p1.AddingStage(std::make_shared(EqExpr( + p1 = p1.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Value(42LL))}))); RealtimePipeline p2 = StartPipeline("test"); - p2 = p2.AddingStage(std::make_shared(EqExpr( + p2 = p2.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Value(42LL))}))); QueryOrPipeline v1 = QueryOrPipeline(p1); @@ -253,7 +253,7 @@ TEST_F(CanonifyEqPipelineTest, EqReturnsTrueForIdenticalPipelines) { TEST_F(CanonifyEqPipelineTest, EqReturnsFalseForDifferentStages) { RealtimePipeline p1 = StartPipeline("test"); - p1 = p1.AddingStage(std::make_shared(EqExpr( + p1 = p1.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Value(42LL))}))); RealtimePipeline p2 = StartPipeline("test"); @@ -266,13 +266,13 @@ TEST_F(CanonifyEqPipelineTest, EqReturnsFalseForDifferentStages) { TEST_F(CanonifyEqPipelineTest, EqReturnsFalseForDifferentParamsInStage) { RealtimePipeline p1 = StartPipeline("test"); - p1 = p1.AddingStage(std::make_shared(EqExpr( + p1 = p1.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Value(42LL))}))); RealtimePipeline p2 = StartPipeline("test"); p2 = p2.AddingStage(std::make_shared( - EqExpr({std::make_shared("bar"), - SharedConstant(Value(42LL))}))); // Different field + EqualExpr({std::make_shared("bar"), + SharedConstant(Value(42LL))}))); // Different field QueryOrPipeline v1 = QueryOrPipeline(p1); QueryOrPipeline v2 = QueryOrPipeline(p2); @@ -281,13 +281,13 @@ TEST_F(CanonifyEqPipelineTest, EqReturnsFalseForDifferentParamsInStage) { TEST_F(CanonifyEqPipelineTest, EqReturnsFalseForDifferentStageOrder) { RealtimePipeline p1 = StartPipeline("test"); - p1 = p1.AddingStage(std::make_shared(EqExpr( + p1 = p1.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Value(42LL))}))); p1 = p1.AddingStage(std::make_shared(10)); RealtimePipeline p2 = StartPipeline("test"); p2 = p2.AddingStage(std::make_shared(10)); - p2 = p2.AddingStage(std::make_shared(EqExpr( + p2 = p2.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Value(42LL))}))); QueryOrPipeline v1 = QueryOrPipeline(p1); diff --git a/Firestore/core/test/unit/core/pipeline/collection_group_test.cc b/Firestore/core/test/unit/core/pipeline/collection_group_test.cc index 4f12261a038..b350caba5ed 100644 --- a/Firestore/core/test/unit/core/pipeline/collection_group_test.cc +++ b/Firestore/core/test/unit/core/pipeline/collection_group_test.cc @@ -55,9 +55,9 @@ using testutil::Array; using testutil::ArrayContainsExpr; using testutil::Doc; using testutil::EqAnyExpr; -using testutil::GtExpr; +using testutil::GreaterThanExpr; using testutil::Map; -using testutil::NeqExpr; +using testutil::NotEqualExpr; using testutil::SharedConstant; using testutil::Value; @@ -229,8 +229,9 @@ TEST_F(CollectionGroupTest, WhereOnValues) { TEST_F(CollectionGroupTest, WhereInequalityOnValues) { RealtimePipeline pipeline = StartPipeline("users"); - auto where_expr = GtExpr({std::make_shared("score"), - SharedConstant(static_cast(80LL))}); + auto where_expr = + GreaterThanExpr({std::make_shared("score"), + SharedConstant(static_cast(80LL))}); pipeline = pipeline.AddingStage(std::make_shared(where_expr)); auto doc1 = Doc("users/bob", 1000, Map("score", 90LL)); @@ -249,8 +250,8 @@ TEST_F(CollectionGroupTest, WhereInequalityOnValues) { TEST_F(CollectionGroupTest, WhereNotEqualOnValues) { RealtimePipeline pipeline = StartPipeline("users"); - auto where_expr = NeqExpr({std::make_shared("score"), - SharedConstant(static_cast(50LL))}); + auto where_expr = NotEqualExpr({std::make_shared("score"), + SharedConstant(static_cast(50LL))}); pipeline = pipeline.AddingStage(std::make_shared(where_expr)); auto doc1 = Doc("users/bob", 1000, Map("score", 90LL)); diff --git a/Firestore/core/test/unit/core/pipeline/collection_test.cc b/Firestore/core/test/unit/core/pipeline/collection_test.cc index b5962732de1..8c70855cf91 100644 --- a/Firestore/core/test/unit/core/pipeline/collection_test.cc +++ b/Firestore/core/test/unit/core/pipeline/collection_test.cc @@ -54,9 +54,9 @@ using testutil::Array; using testutil::ArrayContainsExpr; using testutil::Doc; using testutil::EqAnyExpr; -using testutil::GtExpr; +using testutil::GreaterThanExpr; using testutil::Map; -using testutil::NeqExpr; +using testutil::NotEqualExpr; using testutil::SharedConstant; using testutil::Value; @@ -223,8 +223,9 @@ TEST_F(CollectionTest, WhereOnValues) { TEST_F(CollectionTest, WhereInequalityOnValues) { RealtimePipeline pipeline = StartPipeline("/users"); // Use RealtimePipeline - auto where_expr = GtExpr({std::make_shared("score"), - SharedConstant(static_cast(80LL))}); + auto where_expr = + GreaterThanExpr({std::make_shared("score"), + SharedConstant(static_cast(80LL))}); pipeline = pipeline.AddingStage(std::make_shared(where_expr)); auto doc1 = Doc("users/bob", 1000, Map("score", 90LL)); @@ -238,8 +239,8 @@ TEST_F(CollectionTest, WhereInequalityOnValues) { TEST_F(CollectionTest, WhereNotEqualOnValues) { RealtimePipeline pipeline = StartPipeline("/users"); // Use RealtimePipeline - auto where_expr = NeqExpr({std::make_shared("score"), - SharedConstant(static_cast(50LL))}); + auto where_expr = NotEqualExpr({std::make_shared("score"), + SharedConstant(static_cast(50LL))}); pipeline = pipeline.AddingStage(std::make_shared(where_expr)); auto doc1 = Doc("users/bob", 1000, Map("score", 90LL)); diff --git a/Firestore/core/test/unit/core/pipeline/complex_test.cc b/Firestore/core/test/unit/core/pipeline/complex_test.cc index abfe8b23d51..0c7b365e54f 100644 --- a/Firestore/core/test/unit/core/pipeline/complex_test.cc +++ b/Firestore/core/test/unit/core/pipeline/complex_test.cc @@ -64,12 +64,12 @@ using testutil::AddExpr; using testutil::AndExpr; using testutil::ArrayContainsAnyExpr; using testutil::EqAnyExpr; -using testutil::EqExpr; -using testutil::GtExpr; -using testutil::LteExpr; -using testutil::LtExpr; -using testutil::NeqExpr; +using testutil::EqualExpr; +using testutil::GreaterThanExpr; +using testutil::LessThanExpr; +using testutil::LessThanOrEqualExpr; using testutil::NotEqAnyExpr; +using testutil::NotEqualExpr; using testutil::OrExpr; using testutil::Value; @@ -129,8 +129,8 @@ TEST_F(ComplexPipelineTest, WhereWithMaxNumberOfStages) { for (int i = 1; i <= num_of_fields; ++i) { std::string field_name = "field_" + std::to_string(i); pipeline = pipeline.AddingStage(std::make_shared( - GtExpr({std::make_shared(field_name), - SharedConstant(static_cast(0LL))}))); + GreaterThanExpr({std::make_shared(field_name), + SharedConstant(static_cast(0LL))}))); } EXPECT_THAT(RunPipeline(pipeline, documents), @@ -391,7 +391,7 @@ TEST_F(ComplexPipelineTest, WhereWithNestedAddFunctionMaxDepth) { RealtimePipeline pipeline = StartPipeline("/" + COLLECTION_ID); pipeline = pipeline.AddingStage(std::make_shared( - GtExpr({add_func, SharedConstant(static_cast(0LL))}))); + GreaterThanExpr({add_func, SharedConstant(static_cast(0LL))}))); // Since field_1 starts at 0, adding 1 repeatedly will always result in > 0 EXPECT_THAT(RunPipeline(pipeline, documents), @@ -410,8 +410,8 @@ TEST_F(ComplexPipelineTest, WhereWithLargeNumberOrs) { or_conditions.reserve(num_of_fields); for (int i = 1; i <= num_of_fields; ++i) { std::string field_name = "field_" + std::to_string(i); - // Use LteExpr to match the TS test logic - or_conditions.push_back(LteExpr( + // Use LessThanOrEqualExpr to match the TS test logic + or_conditions.push_back(LessThanOrEqualExpr( {std::make_shared(field_name), SharedConstant(max_value)})); } @@ -439,12 +439,12 @@ TEST_F(ComplexPipelineTest, WhereWithLargeNumberOfConjunctions) { for (int i = 1; i <= num_of_fields; ++i) { std::string field_name = "field_" + std::to_string(i); and_conditions1.push_back( - GtExpr({std::make_shared(field_name), - SharedConstant(static_cast(0LL))})); - // Use LtExpr and a large number for the second condition + GreaterThanExpr({std::make_shared(field_name), + SharedConstant(static_cast(0LL))})); + // Use LessThanExpr and a large number for the second condition and_conditions2.push_back( - LtExpr({std::make_shared(field_name), - SharedConstant(std::numeric_limits::max())})); + LessThanExpr({std::make_shared(field_name), + SharedConstant(std::numeric_limits::max())})); } RealtimePipeline pipeline = StartPipeline("/" + COLLECTION_ID); diff --git a/Firestore/core/test/unit/core/pipeline/disjunctive_test.cc b/Firestore/core/test/unit/core/pipeline/disjunctive_test.cc index f9c89873c24..497554d7bff 100644 --- a/Firestore/core/test/unit/core/pipeline/disjunctive_test.cc +++ b/Firestore/core/test/unit/core/pipeline/disjunctive_test.cc @@ -65,16 +65,16 @@ using testutil::ArrayContainsAllExpr; using testutil::ArrayContainsAnyExpr; using testutil::ArrayContainsExpr; using testutil::EqAnyExpr; -using testutil::EqExpr; -using testutil::GteExpr; -using testutil::GtExpr; +using testutil::EqualExpr; +using testutil::GreaterThanExpr; +using testutil::GreaterThanOrEqualExpr; using testutil::IsNanExpr; using testutil::IsNullExpr; +using testutil::LessThanExpr; +using testutil::LessThanOrEqualExpr; using testutil::LikeExpr; -using testutil::LteExpr; -using testutil::LtExpr; -using testutil::NeqExpr; using testutil::NotEqAnyExpr; +using testutil::NotEqualExpr; using testutil::NotExpr; using testutil::OrExpr; using testutil::XorExpr; @@ -261,7 +261,7 @@ TEST_F(DisjunctivePipelineTest, EqAnyWithAdditionalEqualityDifferentFields) { std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob"), Value("charlie"), Value("diane"), Value("eric")))), - EqExpr( + EqualExpr( {std::make_shared("age"), SharedConstant(Value(10.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( @@ -283,8 +283,8 @@ TEST_F(DisjunctivePipelineTest, EqAnyWithAdditionalEqualitySameField) { AndExpr({EqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("diane"), Value("eric")))), - EqExpr({std::make_shared("name"), - SharedConstant(Value("eric"))})}))); + EqualExpr({std::make_shared("name"), + SharedConstant(Value("eric"))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc5)); } @@ -300,8 +300,8 @@ TEST_F(DisjunctivePipelineTest, pipeline = pipeline.AddingStage(std::make_shared( AndExpr({EqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob")))), - EqExpr({std::make_shared("name"), - SharedConstant(Value("other"))})}))); + EqualExpr({std::make_shared("name"), + SharedConstant(Value("other"))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); // Expect empty result @@ -321,8 +321,9 @@ TEST_F(DisjunctivePipelineTest, EqAnyWithInequalitiesExclusiveRange) { {EqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob"), Value("charlie"), Value("diane")))), - GtExpr({std::make_shared("age"), SharedConstant(Value(10.0))}), - LtExpr( + GreaterThanExpr( + {std::make_shared("age"), SharedConstant(Value(10.0))}), + LessThanExpr( {std::make_shared("age"), SharedConstant(Value(100.0))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), @@ -343,8 +344,9 @@ TEST_F(DisjunctivePipelineTest, EqAnyWithInequalitiesInclusiveRange) { {EqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob"), Value("charlie"), Value("diane")))), - GteExpr({std::make_shared("age"), SharedConstant(Value(10.0))}), - LteExpr( + GreaterThanOrEqualExpr( + {std::make_shared("age"), SharedConstant(Value(10.0))}), + LessThanOrEqualExpr( {std::make_shared("age"), SharedConstant(Value(100.0))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), @@ -365,8 +367,9 @@ TEST_F(DisjunctivePipelineTest, EqAnyWithInequalitiesAndSort) { {EqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob"), Value("charlie"), Value("diane")))), - GtExpr({std::make_shared("age"), SharedConstant(Value(10.0))}), - LtExpr( + GreaterThanExpr( + {std::make_shared("age"), SharedConstant(Value(10.0))}), + LessThanExpr( {std::make_shared("age"), SharedConstant(Value(100.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( @@ -389,7 +392,7 @@ TEST_F(DisjunctivePipelineTest, EqAnyWithNotEqual) { {EqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob"), Value("charlie"), Value("diane")))), - NeqExpr( + NotEqualExpr( {std::make_shared("age"), SharedConstant(Value(100.0))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), @@ -456,7 +459,7 @@ TEST_F(DisjunctivePipelineTest, EqAnyWithExtraEqualitySortOnEqAnyField) { std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob"), Value("charlie"), Value("diane"), Value("eric")))), - EqExpr( + EqualExpr( {std::make_shared("age"), SharedConstant(Value(10.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( @@ -479,7 +482,7 @@ TEST_F(DisjunctivePipelineTest, EqAnyWithExtraEqualitySortOnEquality) { std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob"), Value("charlie"), Value("diane"), Value("eric")))), - EqExpr( + EqualExpr( {std::make_shared("age"), SharedConstant(Value(10.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( @@ -505,7 +508,7 @@ TEST_F(DisjunctivePipelineTest, EqAnyWithInequalityOnSameField) { pipeline = pipeline.AddingStage(std::make_shared(AndExpr( {EqAnyExpr(std::make_shared("age"), SharedConstant(Array(Value(10.0), Value(25.0), Value(100.0)))), - GtExpr( + GreaterThanExpr( {std::make_shared("age"), SharedConstant(Value(20.0))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), @@ -531,7 +534,7 @@ TEST_F( {EqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob"), Value("charlie"), Value("diane")))), - GtExpr( + GreaterThanExpr( {std::make_shared("age"), SharedConstant(Value(20.0))})}))); // Sort field is 'age', which is the inequality field, not the EqAny field // 'name'. The TS test name seems misleading based on the sort field used. @@ -700,8 +703,9 @@ TEST_F(DisjunctivePipelineTest, ArrayContainsAnyWithInequality) { // Note: Comparing an array field with an array constant using LT might // not behave as expected in Firestore backend queries. This test // replicates the TS behavior for pipeline evaluation. - LtExpr({std::make_shared("groups"), - SharedConstant(Array(Value(3LL), Value(4LL), Value(5LL)))})}))); + LessThanExpr( + {std::make_shared("groups"), + SharedConstant(Array(Value(3LL), Value(4LL), Value(5LL)))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc1, doc2, doc4)); @@ -745,10 +749,11 @@ TEST_F(DisjunctivePipelineTest, BasicOr) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {EqExpr({std::make_shared("name"), SharedConstant(Value("bob"))}), - EqExpr( - {std::make_shared("age"), SharedConstant(Value(10.0))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("bob"))}), + EqualExpr({std::make_shared("age"), + SharedConstant(Value(10.0))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc2, doc4)); @@ -763,11 +768,12 @@ TEST_F(DisjunctivePipelineTest, MultipleOr) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {EqExpr({std::make_shared("name"), SharedConstant(Value("bob"))}), - EqExpr( + {EqualExpr( + {std::make_shared("name"), SharedConstant(Value("bob"))}), + EqualExpr( {std::make_shared("name"), SharedConstant(Value("diane"))}), - EqExpr({std::make_shared("age"), SharedConstant(Value(25.0))}), - EqExpr( + EqualExpr({std::make_shared("age"), SharedConstant(Value(25.0))}), + EqualExpr( {std::make_shared("age"), SharedConstant(Value(100.0))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), @@ -782,15 +788,16 @@ TEST_F(DisjunctivePipelineTest, OrMultipleStages) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {EqExpr({std::make_shared("name"), SharedConstant(Value("bob"))}), - EqExpr( - {std::make_shared("age"), SharedConstant(Value(10.0))})}))); pipeline = pipeline.AddingStage(std::make_shared( - OrExpr({EqExpr({std::make_shared("name"), - SharedConstant(Value("diane"))}), - EqExpr({std::make_shared("age"), - SharedConstant(Value(100.0))})}))); + OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("bob"))}), + EqualExpr({std::make_shared("age"), + SharedConstant(Value(10.0))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("diane"))}), + EqualExpr({std::make_shared("age"), + SharedConstant(Value(100.0))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc4)); } @@ -804,14 +811,14 @@ TEST_F(DisjunctivePipelineTest, OrTwoConjunctions) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared( - OrExpr({AndExpr({EqExpr({std::make_shared("name"), - SharedConstant(Value("bob"))}), - EqExpr({std::make_shared("age"), - SharedConstant(Value(25.0))})}), - AndExpr({EqExpr({std::make_shared("name"), - SharedConstant(Value("diane"))}), - EqExpr({std::make_shared("age"), - SharedConstant(Value(10.0))})})}))); + OrExpr({AndExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("bob"))}), + EqualExpr({std::make_shared("age"), + SharedConstant(Value(25.0))})}), + AndExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("diane"))}), + EqualExpr({std::make_shared("age"), + SharedConstant(Value(10.0))})})}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc2, doc4)); @@ -826,12 +833,12 @@ TEST_F(DisjunctivePipelineTest, OrWithInAnd) { // Renamed from TS: or_withInAnd RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared( - AndExpr({OrExpr({EqExpr({std::make_shared("name"), - SharedConstant(Value("bob"))}), - EqExpr({std::make_shared("age"), - SharedConstant(Value(10.0))})}), - LtExpr({std::make_shared("age"), - SharedConstant(Value(80.0))})}))); + AndExpr({OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("bob"))}), + EqualExpr({std::make_shared("age"), + SharedConstant(Value(10.0))})}), + LessThanExpr({std::make_shared("age"), + SharedConstant(Value(80.0))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc2, doc4)); @@ -846,14 +853,14 @@ TEST_F(DisjunctivePipelineTest, AndOfTwoOrs) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared( - AndExpr({OrExpr({EqExpr({std::make_shared("name"), - SharedConstant(Value("bob"))}), - EqExpr({std::make_shared("age"), - SharedConstant(Value(10.0))})}), - OrExpr({EqExpr({std::make_shared("name"), - SharedConstant(Value("diane"))}), - EqExpr({std::make_shared("age"), - SharedConstant(Value(100.0))})})}))); + AndExpr({OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("bob"))}), + EqualExpr({std::make_shared("age"), + SharedConstant(Value(10.0))})}), + OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("diane"))}), + EqualExpr({std::make_shared("age"), + SharedConstant(Value(100.0))})})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc4)); } @@ -867,14 +874,14 @@ TEST_F(DisjunctivePipelineTest, OrOfTwoOrs) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared( - OrExpr({OrExpr({EqExpr({std::make_shared("name"), - SharedConstant(Value("bob"))}), - EqExpr({std::make_shared("age"), - SharedConstant(Value(10.0))})}), - OrExpr({EqExpr({std::make_shared("name"), - SharedConstant(Value("diane"))}), - EqExpr({std::make_shared("age"), - SharedConstant(Value(100.0))})})}))); + OrExpr({OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("bob"))}), + EqualExpr({std::make_shared("age"), + SharedConstant(Value(10.0))})}), + OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("diane"))}), + EqualExpr({std::make_shared("age"), + SharedConstant(Value(100.0))})})}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc2, doc3, doc4)); @@ -888,13 +895,14 @@ TEST_F(DisjunctivePipelineTest, OrWithEmptyRangeInOneDisjunction) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {EqExpr({std::make_shared("name"), SharedConstant(Value("bob"))}), - AndExpr({// This conjunction will always be false - EqExpr({std::make_shared("age"), - SharedConstant(Value(10.0))}), - GtExpr({std::make_shared("age"), - SharedConstant(Value(20.0))})})}))); + pipeline = pipeline.AddingStage(std::make_shared( + OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("bob"))}), + AndExpr({// This conjunction will always be false + EqualExpr({std::make_shared("age"), + SharedConstant(Value(10.0))}), + GreaterThanExpr({std::make_shared("age"), + SharedConstant(Value(20.0))})})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc2)); } @@ -907,11 +915,11 @@ TEST_F(DisjunctivePipelineTest, OrWithSort) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage( - std::make_shared(OrExpr({EqExpr({std::make_shared("name"), - SharedConstant(Value("diane"))}), - GtExpr({std::make_shared("age"), - SharedConstant(Value(20.0))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("diane"))}), + GreaterThanExpr({std::make_shared("age"), + SharedConstant(Value(20.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("age"), Ordering::Direction::ASCENDING)})); @@ -929,10 +937,11 @@ TEST_F(DisjunctivePipelineTest, OrWithInequalityAndSortSameField) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {LtExpr({std::make_shared("age"), SharedConstant(Value(20.0))}), - GtExpr( - {std::make_shared("age"), SharedConstant(Value(50.0))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + OrExpr({LessThanExpr({std::make_shared("age"), + SharedConstant(Value(20.0))}), + GreaterThanExpr({std::make_shared("age"), + SharedConstant(Value(50.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("age"), Ordering::Direction::ASCENDING)})); @@ -949,10 +958,11 @@ TEST_F(DisjunctivePipelineTest, OrWithInequalityAndSortDifferentFields) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {LtExpr({std::make_shared("age"), SharedConstant(Value(20.0))}), - GtExpr( - {std::make_shared("age"), SharedConstant(Value(50.0))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + OrExpr({LessThanExpr({std::make_shared("age"), + SharedConstant(Value(20.0))}), + GreaterThanExpr({std::make_shared("age"), + SharedConstant(Value(50.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("name"), Ordering::Direction::ASCENDING)})); @@ -975,10 +985,11 @@ TEST_F(DisjunctivePipelineTest, OrWithInequalityAndSortMultipleFields) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4, doc5}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {LtExpr({std::make_shared("age"), SharedConstant(Value(80.0))}), - GtExpr({std::make_shared("height"), - SharedConstant(Value(160.0))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + OrExpr({LessThanExpr({std::make_shared("age"), + SharedConstant(Value(80.0))}), + GreaterThanExpr({std::make_shared("height"), + SharedConstant(Value(160.0))})}))); pipeline = pipeline.AddingStage(std::make_shared(std::vector{ Ordering(std::make_unique("age"), @@ -1004,11 +1015,11 @@ TEST_F(DisjunctivePipelineTest, OrWithSortOnPartialMissingField) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage( - std::make_shared(OrExpr({EqExpr({std::make_shared("name"), - SharedConstant(Value("diane"))}), - GtExpr({std::make_shared("age"), - SharedConstant(Value(20.0))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("diane"))}), + GreaterThanExpr({std::make_shared("age"), + SharedConstant(Value(20.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("age"), Ordering::Direction::ASCENDING)})); @@ -1027,11 +1038,11 @@ TEST_F(DisjunctivePipelineTest, OrWithLimit) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage( - std::make_shared(OrExpr({EqExpr({std::make_shared("name"), - SharedConstant(Value("diane"))}), - GtExpr({std::make_shared("age"), - SharedConstant(Value(20.0))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + OrExpr({EqualExpr({std::make_shared("name"), + SharedConstant(Value("diane"))}), + GreaterThanExpr({std::make_shared("age"), + SharedConstant(Value(20.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("age"), Ordering::Direction::ASCENDING)})); @@ -1059,7 +1070,7 @@ TEST_F(DisjunctivePipelineTest, OrIsNullAndEqOnSameField) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {EqExpr({std::make_shared("a"), SharedConstant(Value(1LL))}), + {EqualExpr({std::make_shared("a"), SharedConstant(Value(1LL))}), IsNullExpr(std::make_shared("a"))}))); // Expect docs where a==1 (doc1, doc2, doc3) or a is null (doc4) @@ -1079,7 +1090,7 @@ TEST_F(DisjunctivePipelineTest, OrIsNullAndEqOnDifferentField) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {EqExpr({std::make_shared("b"), SharedConstant(Value(1LL))}), + {EqualExpr({std::make_shared("b"), SharedConstant(Value(1LL))}), IsNullExpr(std::make_shared("a"))}))); // Expect docs where b==1 (doc3) or a is null (doc4) @@ -1100,7 +1111,8 @@ TEST_F(DisjunctivePipelineTest, OrIsNotNullAndEqOnSameField) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(OrExpr({ // Note: TS test uses gt(1), C++ uses gt(1) here too. - GtExpr({std::make_shared("a"), SharedConstant(Value(1LL))}), + GreaterThanExpr( + {std::make_shared("a"), SharedConstant(Value(1LL))}), NotExpr(IsNullExpr(std::make_shared("a"))) // isNotNull }))); @@ -1122,7 +1134,7 @@ TEST_F(DisjunctivePipelineTest, OrIsNotNullAndEqOnDifferentField) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(OrExpr({ - EqExpr({std::make_shared("b"), SharedConstant(Value(1LL))}), + EqualExpr({std::make_shared("b"), SharedConstant(Value(1LL))}), NotExpr(IsNullExpr(std::make_shared("a"))) // isNotNull }))); @@ -1282,7 +1294,7 @@ TEST_F(DisjunctivePipelineTest, NotEqAnyWithAdditionalEqualityDifferentFields) { pipeline = pipeline.AddingStage(std::make_shared(AndExpr( {NotEqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob")))), - EqExpr( + EqualExpr( {std::make_shared("age"), SharedConstant(Value(10.0))})}))); // Expect docs where name is not alice/bob (doc3, doc4, doc5) AND age is 10 @@ -1303,8 +1315,8 @@ TEST_F(DisjunctivePipelineTest, NotEqAnyWithAdditionalEqualitySameField) { pipeline = pipeline.AddingStage(std::make_shared(AndExpr( {NotEqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("diane")))), - EqExpr({std::make_shared("name"), - SharedConstant(Value("eric"))})}))); + EqualExpr({std::make_shared("name"), + SharedConstant(Value("eric"))})}))); // Expect docs where name is not alice/diane (doc2, doc3, doc5) AND name is // eric (doc5) @@ -1323,8 +1335,9 @@ TEST_F(DisjunctivePipelineTest, NotEqAnyWithInequalitiesExclusiveRange) { pipeline = pipeline.AddingStage(std::make_shared(AndExpr( {NotEqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("charlie")))), - GtExpr({std::make_shared("age"), SharedConstant(Value(10.0))}), - LtExpr( + GreaterThanExpr( + {std::make_shared("age"), SharedConstant(Value(10.0))}), + LessThanExpr( {std::make_shared("age"), SharedConstant(Value(100.0))})}))); // Expect docs where name is not alice/charlie (doc2, doc4, doc5) AND age > 10 @@ -1345,8 +1358,9 @@ TEST_F(DisjunctivePipelineTest, NotEqAnyWithInequalitiesInclusiveRange) { {NotEqAnyExpr( std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob"), Value("eric")))), - GteExpr({std::make_shared("age"), SharedConstant(Value(10.0))}), - LteExpr( + GreaterThanOrEqualExpr( + {std::make_shared("age"), SharedConstant(Value(10.0))}), + LessThanOrEqualExpr( {std::make_shared("age"), SharedConstant(Value(100.0))})}))); // Expect docs where name is not alice/bob/eric (doc3, doc4) AND age >= 10 AND @@ -1367,8 +1381,9 @@ TEST_F(DisjunctivePipelineTest, NotEqAnyWithInequalitiesAndSort) { pipeline = pipeline.AddingStage(std::make_shared(AndExpr( {NotEqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("diane")))), - GtExpr({std::make_shared("age"), SharedConstant(Value(10.0))}), - LteExpr( + GreaterThanExpr( + {std::make_shared("age"), SharedConstant(Value(10.0))}), + LessThanOrEqualExpr( {std::make_shared("age"), SharedConstant(Value(100.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( @@ -1391,7 +1406,7 @@ TEST_F(DisjunctivePipelineTest, NotEqAnyWithNotEqual) { pipeline = pipeline.AddingStage(std::make_shared(AndExpr( {NotEqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob")))), - NeqExpr( + NotEqualExpr( {std::make_shared("age"), SharedConstant(Value(100.0))})}))); // Expect docs where name is not alice/bob (doc3, doc4, doc5) AND age is not @@ -1451,7 +1466,7 @@ TEST_F(DisjunctivePipelineTest, NotEqAnyWithExtraEqualitySortOnNotEqAnyField) { pipeline = pipeline.AddingStage(std::make_shared(AndExpr( {NotEqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob")))), - EqExpr( + EqualExpr( {std::make_shared("age"), SharedConstant(Value(10.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( @@ -1474,7 +1489,7 @@ TEST_F(DisjunctivePipelineTest, NotEqAnyWithExtraEqualitySortOnEquality) { pipeline = pipeline.AddingStage(std::make_shared(AndExpr( {NotEqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("bob")))), - EqExpr( + EqualExpr( {std::make_shared("age"), SharedConstant(Value(10.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( @@ -1497,8 +1512,8 @@ TEST_F(DisjunctivePipelineTest, NotEqAnyWithInequalityOnSameField) { pipeline = pipeline.AddingStage(std::make_shared( AndExpr({NotEqAnyExpr(std::make_shared("age"), SharedConstant(Array(Value(10.0), Value(100.0)))), - GtExpr({std::make_shared("age"), - SharedConstant(Value(20.0))})}))); + GreaterThanExpr({std::make_shared("age"), + SharedConstant(Value(20.0))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("age"), Ordering::Direction::ASCENDING)})); @@ -1523,7 +1538,7 @@ TEST_F( pipeline = pipeline.AddingStage(std::make_shared(AndExpr( {NotEqAnyExpr(std::make_shared("name"), SharedConstant(Array(Value("alice"), Value("diane")))), - GtExpr( + GreaterThanExpr( {std::make_shared("age"), SharedConstant(Value(20.0))})}))); // Sort field is 'age', the inequality field. TS name was misleading. pipeline = pipeline.AddingStage( @@ -1550,26 +1565,28 @@ TEST_F(DisjunctivePipelineTest, NoLimitOnNumOfDisjunctions) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {EqExpr( + {EqualExpr( {std::make_shared("name"), SharedConstant(Value("alice"))}), - EqExpr({std::make_shared("name"), SharedConstant(Value("bob"))}), - EqExpr( + EqualExpr( + {std::make_shared("name"), SharedConstant(Value("bob"))}), + EqualExpr( {std::make_shared("name"), SharedConstant(Value("charlie"))}), - EqExpr( + EqualExpr( {std::make_shared("name"), SharedConstant(Value("diane"))}), - EqExpr({std::make_shared("age"), SharedConstant(Value(10.0))}), - EqExpr({std::make_shared("age"), SharedConstant(Value(25.0))}), - EqExpr({std::make_shared("age"), - SharedConstant(Value(40.0))}), // No doc matches this - EqExpr({std::make_shared("age"), SharedConstant(Value(100.0))}), - EqExpr( + EqualExpr({std::make_shared("age"), SharedConstant(Value(10.0))}), + EqualExpr({std::make_shared("age"), SharedConstant(Value(25.0))}), + EqualExpr({std::make_shared("age"), + SharedConstant(Value(40.0))}), // No doc matches this + EqualExpr( + {std::make_shared("age"), SharedConstant(Value(100.0))}), + EqualExpr( {std::make_shared("height"), SharedConstant(Value(150.0))}), - EqExpr({std::make_shared("height"), - SharedConstant(Value(160.0))}), // No doc matches this - EqExpr( + EqualExpr({std::make_shared("height"), + SharedConstant(Value(160.0))}), // No doc matches this + EqualExpr( {std::make_shared("height"), SharedConstant(Value(170.0))}), - EqExpr({std::make_shared("height"), - SharedConstant(Value(180.0))})}))); + EqualExpr({std::make_shared("height"), + SharedConstant(Value(180.0))})}))); // Since each doc matches at least one condition, all should be returned. EXPECT_THAT(RunPipeline(pipeline, documents), diff --git a/Firestore/core/test/unit/core/pipeline/error_handling_test.cc b/Firestore/core/test/unit/core/pipeline/error_handling_test.cc index 280749051c1..8db238e591f 100644 --- a/Firestore/core/test/unit/core/pipeline/error_handling_test.cc +++ b/Firestore/core/test/unit/core/pipeline/error_handling_test.cc @@ -68,16 +68,16 @@ using testutil::ArrayContainsAnyExpr; using testutil::ArrayContainsExpr; using testutil::DivideExpr; // Added for divide test using testutil::EqAnyExpr; -using testutil::EqExpr; -using testutil::GteExpr; -using testutil::GtExpr; +using testutil::EqualExpr; +using testutil::GreaterThanExpr; +using testutil::GreaterThanOrEqualExpr; using testutil::IsNanExpr; using testutil::IsNullExpr; +using testutil::LessThanExpr; +using testutil::LessThanOrEqualExpr; using testutil::LikeExpr; -using testutil::LteExpr; -using testutil::LtExpr; -using testutil::NeqExpr; using testutil::NotEqAnyExpr; +using testutil::NotEqualExpr; using testutil::NotExpr; using testutil::OrExpr; using testutil::XorExpr; @@ -123,16 +123,17 @@ TEST_F(ErrorHandlingPipelineTest, WherePartialErrorOr) { RealtimePipeline pipeline = StartPipeline("/k"); pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {EqExpr({std::make_shared("a"), - SharedConstant(Value(true))}), // Expects boolean true - EqExpr({std::make_shared("b"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("c"), SharedConstant(Value(true))})}))); + {EqualExpr({std::make_shared("a"), + SharedConstant(Value(true))}), // Expects boolean true + EqualExpr({std::make_shared("b"), SharedConstant(Value(true))}), + EqualExpr( + {std::make_shared("c"), SharedConstant(Value(true))})}))); // In Firestore, comparisons between different types are generally false. // The OR evaluates to true if *any* of the fields 'a', 'b', or 'c' is the // boolean value `true`. All documents have at least one field that is boolean // `true` or can be evaluated. Assuming type mismatches evaluate to false in - // EqExpr for OR. + // EqualExpr for OR. EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc1, doc2, doc3, doc4, doc5, doc6)); } @@ -164,12 +165,13 @@ TEST_F(ErrorHandlingPipelineTest, WherePartialErrorAnd) { RealtimePipeline pipeline = StartPipeline("k"); pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {EqExpr({std::make_shared("a"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("b"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("c"), SharedConstant(Value(true))})}))); + {EqualExpr({std::make_shared("a"), SharedConstant(Value(true))}), + EqualExpr({std::make_shared("b"), SharedConstant(Value(true))}), + EqualExpr( + {std::make_shared("c"), SharedConstant(Value(true))})}))); - // AND requires all conditions to be true. Type mismatches evaluate EqExpr to - // false. Only doc7 has a=true, b=true, AND c=true. + // AND requires all conditions to be true. Type mismatches evaluate EqualExpr + // to false. Only doc7 has a=true, b=true, AND c=true. EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc7)); } @@ -201,12 +203,13 @@ TEST_F(ErrorHandlingPipelineTest, WherePartialErrorXor) { RealtimePipeline pipeline = StartPipeline("k"); pipeline = pipeline.AddingStage(std::make_shared(XorExpr( - {// Casting might not work directly, using EqExpr for boolean check - EqExpr({std::make_shared("a"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("b"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("c"), SharedConstant(Value(true))})}))); + {// Casting might not work directly, using EqualExpr for boolean check + EqualExpr({std::make_shared("a"), SharedConstant(Value(true))}), + EqualExpr({std::make_shared("b"), SharedConstant(Value(true))}), + EqualExpr( + {std::make_shared("c"), SharedConstant(Value(true))})}))); - // Assuming type mismatches evaluate EqExpr to false: + // Assuming type mismatches evaluate EqualExpr to false: // doc1: F ^ T ^ F = T // doc2: T ^ F ^ F = T // doc3: T ^ F ^ F = T @@ -243,7 +246,7 @@ TEST_F(ErrorHandlingPipelineTest, WhereErrorProducingFunctionReturnsEmpty) { RealtimePipeline pipeline = StartPipeline("k"); // Division operation with string constants - this should likely cause an // evaluation error. - pipeline = pipeline.AddingStage(std::make_shared(EqExpr({ + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr({ DivideExpr({SharedConstant(Value("100")), SharedConstant(Value("50"))}), // Error here SharedConstant(Value(2LL)) // Comparing result to integer 2 diff --git a/Firestore/core/test/unit/core/pipeline/inequality_test.cc b/Firestore/core/test/unit/core/pipeline/inequality_test.cc index d3ede6de7af..ca00529072c 100644 --- a/Firestore/core/test/unit/core/pipeline/inequality_test.cc +++ b/Firestore/core/test/unit/core/pipeline/inequality_test.cc @@ -71,16 +71,16 @@ using testutil::ArrayContainsAnyExpr; using testutil::ArrayContainsExpr; using testutil::DivideExpr; using testutil::EqAnyExpr; -using testutil::EqExpr; -using testutil::GteExpr; -using testutil::GtExpr; +using testutil::EqualExpr; +using testutil::GreaterThanExpr; +using testutil::GreaterThanOrEqualExpr; using testutil::IsNanExpr; using testutil::IsNullExpr; +using testutil::LessThanExpr; +using testutil::LessThanOrEqualExpr; using testutil::LikeExpr; -using testutil::LteExpr; -using testutil::LtExpr; -using testutil::NeqExpr; using testutil::NotEqAnyExpr; +using testutil::NotEqualExpr; using testutil::NotExpr; using testutil::OrExpr; using testutil::XorExpr; @@ -103,8 +103,8 @@ TEST_F(InequalityPipelineTest, GreaterThan) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - GtExpr({std::make_shared("score"), SharedConstant(Value(90LL))}))); + pipeline = pipeline.AddingStage(std::make_shared(GreaterThanExpr( + {std::make_shared("score"), SharedConstant(Value(90LL))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc3)); } @@ -116,8 +116,9 @@ TEST_F(InequalityPipelineTest, GreaterThanOrEqual) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(GteExpr( - {std::make_shared("score"), SharedConstant(Value(90LL))}))); + pipeline = + pipeline.AddingStage(std::make_shared(GreaterThanOrEqualExpr( + {std::make_shared("score"), SharedConstant(Value(90LL))}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc1, doc3)); @@ -130,8 +131,8 @@ TEST_F(InequalityPipelineTest, LessThan) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - LtExpr({std::make_shared("score"), SharedConstant(Value(90LL))}))); + pipeline = pipeline.AddingStage(std::make_shared(LessThanExpr( + {std::make_shared("score"), SharedConstant(Value(90LL))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc2)); } @@ -143,7 +144,7 @@ TEST_F(InequalityPipelineTest, LessThanOrEqual) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(LteExpr( + pipeline = pipeline.AddingStage(std::make_shared(LessThanOrEqualExpr( {std::make_shared("score"), SharedConstant(Value(90LL))}))); EXPECT_THAT(RunPipeline(pipeline, documents), @@ -157,7 +158,7 @@ TEST_F(InequalityPipelineTest, NotEqual) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(NeqExpr( + pipeline = pipeline.AddingStage(std::make_shared(NotEqualExpr( {std::make_shared("score"), SharedConstant(Value(90LL))}))); EXPECT_THAT(RunPipeline(pipeline, documents), @@ -187,7 +188,7 @@ TEST_F(InequalityPipelineTest, NotEqualReturnsMixedTypes) { doc5, doc6, doc7, doc8}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(NeqExpr( + pipeline = pipeline.AddingStage(std::make_shared(NotEqualExpr( {std::make_shared("score"), SharedConstant(Value(90LL))}))); // Neq returns true for different types. @@ -212,8 +213,8 @@ TEST_F(InequalityPipelineTest, ComparisonHasImplicitBound) { doc5, doc6, doc7, doc8}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - GtExpr({std::make_shared("score"), SharedConstant(Value(42LL))}))); + pipeline = pipeline.AddingStage(std::make_shared(GreaterThanExpr( + {std::make_shared("score"), SharedConstant(Value(42LL))}))); // Only numeric types greater than 42 are matched. EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc2)); @@ -248,11 +249,12 @@ TEST_F(InequalityPipelineTest, NotComparisonReturnsMixedType) { doc5, doc6, doc7, doc8}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(NotExpr(GtExpr( - {std::make_shared("score"), SharedConstant(Value(90LL))})))); + pipeline = + pipeline.AddingStage(std::make_shared(NotExpr(GreaterThanExpr( + {std::make_shared("score"), SharedConstant(Value(90LL))})))); // NOT (score > 90). Comparison is only true for score=100.0. NOT flips it. - // Type mismatches result in false for GtExpr, NOT flips to true. + // Type mismatches result in false for GreaterThanExpr, NOT flips to true. EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc1, doc3, doc4, doc5, doc6, doc7, doc8)); } @@ -269,8 +271,8 @@ TEST_F(InequalityPipelineTest, InequalityWithEqualityOnDifferentField) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {EqExpr({std::make_shared("rank"), SharedConstant(Value(2LL))}), - GtExpr( + {EqualExpr({std::make_shared("rank"), SharedConstant(Value(2LL))}), + GreaterThanExpr( {std::make_shared("score"), SharedConstant(Value(80LL))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc1)); @@ -284,10 +286,11 @@ TEST_F(InequalityPipelineTest, InequalityWithEqualityOnSameField) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {EqExpr({std::make_shared("score"), SharedConstant(Value(90LL))}), - GtExpr( - {std::make_shared("score"), SharedConstant(Value(80LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({EqualExpr({std::make_shared("score"), + SharedConstant(Value(90LL))}), + GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(80LL))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc1)); } @@ -299,8 +302,9 @@ TEST_F(InequalityPipelineTest, WithSortOnSameField) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(GteExpr( - {std::make_shared("score"), SharedConstant(Value(90LL))}))); + pipeline = + pipeline.AddingStage(std::make_shared(GreaterThanOrEqualExpr( + {std::make_shared("score"), SharedConstant(Value(90LL))}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("score"), Ordering::Direction::ASCENDING)})); @@ -316,8 +320,9 @@ TEST_F(InequalityPipelineTest, WithSortOnDifferentFields) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(GteExpr( - {std::make_shared("score"), SharedConstant(Value(90LL))}))); + pipeline = + pipeline.AddingStage(std::make_shared(GreaterThanOrEqualExpr( + {std::make_shared("score"), SharedConstant(Value(90LL))}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("rank"), Ordering::Direction::ASCENDING)})); @@ -335,10 +340,11 @@ TEST_F(InequalityPipelineTest, WithOrOnSingleField) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {GtExpr({std::make_shared("score"), SharedConstant(Value(90LL))}), - LtExpr( - {std::make_shared("score"), SharedConstant(Value(60LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + OrExpr({GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(90LL))}), + LessThanExpr({std::make_shared("score"), + SharedConstant(Value(60LL))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc2, doc3)); @@ -355,10 +361,11 @@ TEST_F(InequalityPipelineTest, WithOrOnDifferentFields) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {GtExpr({std::make_shared("score"), SharedConstant(Value(80LL))}), - LtExpr( - {std::make_shared("rank"), SharedConstant(Value(2LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + OrExpr({GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(80LL))}), + LessThanExpr({std::make_shared("rank"), + SharedConstant(Value(2LL))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc1, doc3)); @@ -375,7 +382,8 @@ TEST_F(InequalityPipelineTest, WithEqAnyOnSingleField) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {GtExpr({std::make_shared("score"), SharedConstant(Value(80LL))}), + {GreaterThanExpr( + {std::make_shared("score"), SharedConstant(Value(80LL))}), EqAnyExpr( std::make_shared("score"), SharedConstant(Array(Value(50LL), Value(80LL), Value(97LL))))}))); @@ -396,7 +404,8 @@ TEST_F(InequalityPipelineTest, WithEqAnyOnDifferentFields) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {LtExpr({std::make_shared("rank"), SharedConstant(Value(3LL))}), + {LessThanExpr( + {std::make_shared("rank"), SharedConstant(Value(3LL))}), EqAnyExpr( std::make_shared("score"), SharedConstant(Array(Value(50LL), Value(80LL), Value(97LL))))}))); @@ -415,7 +424,8 @@ TEST_F(InequalityPipelineTest, WithNotEqAnyOnSingleField) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {GtExpr({std::make_shared("score"), SharedConstant(Value(80LL))}), + {GreaterThanExpr( + {std::make_shared("score"), SharedConstant(Value(80LL))}), NotEqAnyExpr(std::make_shared("score"), SharedConstant(Array(Value(90LL), Value(95LL))))}))); @@ -488,7 +498,8 @@ TEST_F(InequalityPipelineTest, WithNotEqAnyOnDifferentFields) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {LtExpr({std::make_shared("rank"), SharedConstant(Value(3LL))}), + {LessThanExpr( + {std::make_shared("rank"), SharedConstant(Value(3LL))}), NotEqAnyExpr(std::make_shared("score"), SharedConstant(Array(Value(90LL), Value(95LL))))}))); @@ -510,8 +521,8 @@ TEST_F(InequalityPipelineTest, SortByEquality) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {EqExpr({std::make_shared("rank"), SharedConstant(Value(2LL))}), - GtExpr( + {EqualExpr({std::make_shared("rank"), SharedConstant(Value(2LL))}), + GreaterThanExpr( {std::make_shared("score"), SharedConstant(Value(80LL))})}))); pipeline = pipeline.AddingStage(std::make_shared( std::vector{Ordering(std::make_unique("rank"), @@ -539,7 +550,7 @@ TEST_F(InequalityPipelineTest, WithEqAnySortByEquality) { pipeline = pipeline.AddingStage(std::make_shared(AndExpr( {EqAnyExpr(std::make_shared("rank"), SharedConstant(Array(Value(2LL), Value(3LL), Value(4LL)))), - GtExpr( + GreaterThanExpr( {std::make_shared("score"), SharedConstant(Value(80LL))})}))); pipeline = pipeline.AddingStage(std::make_shared( std::vector{Ordering(std::make_unique("rank"), @@ -567,10 +578,11 @@ TEST_F(InequalityPipelineTest, WithArray) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {LteExpr({std::make_shared("scores"), - SharedConstant(Array(Value(90LL), Value(90LL), Value(90LL)))}), - GtExpr({std::make_shared("rounds"), - SharedConstant(Array(Value(1LL), Value(2LL)))})}))); + {LessThanOrEqualExpr( + {std::make_shared("scores"), + SharedConstant(Array(Value(90LL), Value(90LL), Value(90LL)))}), + GreaterThanExpr({std::make_shared("rounds"), + SharedConstant(Array(Value(1LL), Value(2LL)))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc1)); } @@ -597,8 +609,9 @@ TEST_F(InequalityPipelineTest, RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared(AndExpr({ - LteExpr({std::make_shared("scores"), - SharedConstant(Array(Value(90LL), Value(90LL), Value(90LL)))}), + LessThanOrEqualExpr( + {std::make_shared("scores"), + SharedConstant(Array(Value(90LL), Value(90LL), Value(90LL)))}), ArrayContainsExpr( {std::make_shared("rounds"), SharedConstant(Value(3LL))}) // TS used ArrayContains here @@ -616,8 +629,8 @@ TEST_F(InequalityPipelineTest, WithSortAndLimit) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - GtExpr({std::make_shared("score"), SharedConstant(Value(80LL))}))); + pipeline = pipeline.AddingStage(std::make_shared(GreaterThanExpr( + {std::make_shared("score"), SharedConstant(Value(80LL))}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("rank"), Ordering::Direction::ASCENDING)})); @@ -636,10 +649,11 @@ TEST_F(InequalityPipelineTest, MultipleInequalitiesOnSingleField) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {GtExpr({std::make_shared("score"), SharedConstant(Value(90LL))}), - LtExpr({std::make_shared("score"), - SharedConstant(Value(100LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(90LL))}), + LessThanExpr({std::make_shared("score"), + SharedConstant(Value(100LL))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc3)); } @@ -656,10 +670,11 @@ TEST_F(InequalityPipelineTest, PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {GtExpr({std::make_shared("score"), SharedConstant(Value(90LL))}), - LtExpr( - {std::make_shared("rank"), SharedConstant(Value(2LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(90LL))}), + LessThanExpr({std::make_shared("rank"), + SharedConstant(Value(2LL))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc3)); } @@ -677,10 +692,11 @@ TEST_F(InequalityPipelineTest, PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {GtExpr({std::make_shared("score"), SharedConstant(Value(80LL))}), - LtExpr( - {std::make_shared("rank"), SharedConstant(Value(3LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(80LL))}), + LessThanExpr({std::make_shared("rank"), + SharedConstant(Value(3LL))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc1, doc3)); @@ -699,10 +715,11 @@ TEST_F(InequalityPipelineTest, MultipleInequalitiesOnDifferentFieldsAllMatch) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {GtExpr({std::make_shared("score"), SharedConstant(Value(40LL))}), - LtExpr( - {std::make_shared("rank"), SharedConstant(Value(4LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(40LL))}), + LessThanExpr({std::make_shared("rank"), + SharedConstant(Value(4LL))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc1, doc2, doc3)); @@ -718,10 +735,11 @@ TEST_F(InequalityPipelineTest, MultipleInequalitiesOnDifferentFieldsNoMatch) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {LtExpr({std::make_shared("score"), SharedConstant(Value(90LL))}), - GtExpr( - {std::make_shared("rank"), SharedConstant(Value(3LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({LessThanExpr({std::make_shared("score"), + SharedConstant(Value(90LL))}), + GreaterThanExpr({std::make_shared("rank"), + SharedConstant(Value(3LL))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -739,12 +757,15 @@ TEST_F(InequalityPipelineTest, MultipleInequalitiesWithBoundedRanges) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {GtExpr({std::make_shared("rank"), SharedConstant(Value(0LL))}), - LtExpr({std::make_shared("rank"), SharedConstant(Value(4LL))}), - GtExpr({std::make_shared("score"), SharedConstant(Value(80LL))}), - LtExpr( - {std::make_shared("score"), SharedConstant(Value(95LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({GreaterThanExpr({std::make_shared("rank"), + SharedConstant(Value(0LL))}), + LessThanExpr({std::make_shared("rank"), + SharedConstant(Value(4LL))}), + GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(80LL))}), + LessThanExpr({std::make_shared("score"), + SharedConstant(Value(95LL))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc1)); } @@ -758,10 +779,11 @@ TEST_F(InequalityPipelineTest, MultipleInequalitiesWithSingleSortAsc) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {LtExpr({std::make_shared("rank"), SharedConstant(Value(3LL))}), - GtExpr( - {std::make_shared("score"), SharedConstant(Value(80LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({LessThanExpr({std::make_shared("rank"), + SharedConstant(Value(3LL))}), + GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(80LL))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("rank"), Ordering::Direction::ASCENDING)})); @@ -778,10 +800,11 @@ TEST_F(InequalityPipelineTest, MultipleInequalitiesWithSingleSortDesc) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {LtExpr({std::make_shared("rank"), SharedConstant(Value(3LL))}), - GtExpr( - {std::make_shared("score"), SharedConstant(Value(80LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({LessThanExpr({std::make_shared("rank"), + SharedConstant(Value(3LL))}), + GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(80LL))})}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("rank"), Ordering::Direction::DESCENDING)})); @@ -798,10 +821,11 @@ TEST_F(InequalityPipelineTest, MultipleInequalitiesWithMultipleSortAsc) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {LtExpr({std::make_shared("rank"), SharedConstant(Value(3LL))}), - GtExpr( - {std::make_shared("score"), SharedConstant(Value(80LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({LessThanExpr({std::make_shared("rank"), + SharedConstant(Value(3LL))}), + GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(80LL))})}))); pipeline = pipeline.AddingStage(std::make_shared( std::vector{Ordering(std::make_unique("rank"), Ordering::Direction::ASCENDING), @@ -820,10 +844,11 @@ TEST_F(InequalityPipelineTest, MultipleInequalitiesWithMultipleSortDesc) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {LtExpr({std::make_shared("rank"), SharedConstant(Value(3LL))}), - GtExpr( - {std::make_shared("score"), SharedConstant(Value(80LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({LessThanExpr({std::make_shared("rank"), + SharedConstant(Value(3LL))}), + GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(80LL))})}))); pipeline = pipeline.AddingStage(std::make_shared( std::vector{Ordering(std::make_unique("rank"), Ordering::Direction::DESCENDING), @@ -843,10 +868,11 @@ TEST_F(InequalityPipelineTest, PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {LtExpr({std::make_shared("rank"), SharedConstant(Value(3LL))}), - GtExpr( - {std::make_shared("score"), SharedConstant(Value(80LL))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({LessThanExpr({std::make_shared("rank"), + SharedConstant(Value(3LL))}), + GreaterThanExpr({std::make_shared("score"), + SharedConstant(Value(80LL))})}))); pipeline = pipeline.AddingStage(std::make_shared( std::vector{Ordering(std::make_unique("score"), Ordering::Direction::DESCENDING), diff --git a/Firestore/core/test/unit/core/pipeline/nested_properties_test.cc b/Firestore/core/test/unit/core/pipeline/nested_properties_test.cc index 84b2197c725..bdeaf3fa51f 100644 --- a/Firestore/core/test/unit/core/pipeline/nested_properties_test.cc +++ b/Firestore/core/test/unit/core/pipeline/nested_properties_test.cc @@ -66,13 +66,13 @@ using testutil::Map; using testutil::SharedConstant; using testutil::Value; // Expression helpers -using testutil::EqExpr; +using testutil::EqualExpr; using testutil::ExistsExpr; -using testutil::GteExpr; -using testutil::GtExpr; +using testutil::GreaterThanExpr; +using testutil::GreaterThanOrEqualExpr; using testutil::IsNullExpr; -using testutil::LtExpr; -using testutil::NeqExpr; +using testutil::LessThanExpr; +using testutil::NotEqualExpr; using testutil::NotExpr; // Test Fixture for Nested Properties Pipeline tests @@ -129,8 +129,8 @@ TEST_F(NestedPropertiesPipelineTest, WhereEqualityDeeplyNested) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("a.b.c.d.e.f.g.h.i.j.k"), - SharedConstant(Value(42LL))}))); + EqualExpr({std::make_shared("a.b.c.d.e.f.g.h.i.j.k"), + SharedConstant(Value(42LL))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc1)); } @@ -180,8 +180,8 @@ TEST_F(NestedPropertiesPipelineTest, WhereInequalityDeeplyNested) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared( - GteExpr({std::make_shared("a.b.c.d.e.f.g.h.i.j.k"), - SharedConstant(Value(0LL))}))); + GreaterThanOrEqualExpr({std::make_shared("a.b.c.d.e.f.g.h.i.j.k"), + SharedConstant(Value(0LL))}))); pipeline = pipeline.AddingStage(std::make_shared(std::vector{ Ordering(std::make_unique(FieldPath::kDocumentKeyPath), @@ -205,9 +205,9 @@ TEST_F(NestedPropertiesPipelineTest, WhereEquality) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage( - std::make_shared(EqExpr({std::make_shared("address.street"), - SharedConstant(Value("76"))}))); + pipeline = pipeline.AddingStage(std::make_shared( + EqualExpr({std::make_shared("address.street"), + SharedConstant(Value("76"))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc2)); } @@ -227,11 +227,11 @@ TEST_F(NestedPropertiesPipelineTest, MultipleFilters) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("address.city"), - SharedConstant(Value("San Francisco"))}))); - pipeline = pipeline.AddingStage( - std::make_shared(GtExpr({std::make_shared("address.zip"), - SharedConstant(Value(90000LL))}))); + EqualExpr({std::make_shared("address.city"), + SharedConstant(Value("San Francisco"))}))); + pipeline = pipeline.AddingStage(std::make_shared( + GreaterThanExpr({std::make_shared("address.zip"), + SharedConstant(Value(90000LL))}))); // city == "San Francisco" AND zip > 90000 // doc1: T AND 94105 > 90000 (T) -> True @@ -255,13 +255,13 @@ TEST_F(NestedPropertiesPipelineTest, MultipleFiltersRedundant) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline = StartPipeline("/users"); + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("address"), + SharedConstant(Map( // Use testutil::Map helper + "city", "San Francisco", "state", "CA", "zip", 94105LL))}))); pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("address"), - SharedConstant(Map( // Use testutil::Map helper - "city", "San Francisco", "state", "CA", "zip", 94105LL))}))); - pipeline = pipeline.AddingStage( - std::make_shared(GtExpr({std::make_shared("address.zip"), - SharedConstant(Value(90000LL))}))); + GreaterThanExpr({std::make_shared("address.zip"), + SharedConstant(Value(90000LL))}))); // address == {city: SF, state: CA, zip: 94105} AND address.zip > 90000 // doc1: T AND 94105 > 90000 (T) -> True @@ -288,11 +288,11 @@ TEST_F(NestedPropertiesPipelineTest, MultipleFiltersWithCompositeIndex) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("address.city"), - SharedConstant(Value("San Francisco"))}))); - pipeline = pipeline.AddingStage( - std::make_shared(GtExpr({std::make_shared("address.zip"), - SharedConstant(Value(90000LL))}))); + EqualExpr({std::make_shared("address.city"), + SharedConstant(Value("San Francisco"))}))); + pipeline = pipeline.AddingStage(std::make_shared( + GreaterThanExpr({std::make_shared("address.zip"), + SharedConstant(Value(90000LL))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc1)); } @@ -314,26 +314,26 @@ TEST_F(NestedPropertiesPipelineTest, WhereInequality) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4}; RealtimePipeline pipeline1 = StartPipeline("/users"); - pipeline1 = pipeline1.AddingStage( - std::make_shared(GtExpr({std::make_shared("address.zip"), - SharedConstant(Value(90000LL))}))); + pipeline1 = pipeline1.AddingStage(std::make_shared( + GreaterThanExpr({std::make_shared("address.zip"), + SharedConstant(Value(90000LL))}))); EXPECT_THAT(RunPipeline(pipeline1, documents), ElementsAre(doc1, doc3)); RealtimePipeline pipeline2 = StartPipeline("/users"); - pipeline2 = pipeline2.AddingStage( - std::make_shared(LtExpr({std::make_shared("address.zip"), - SharedConstant(Value(90000LL))}))); + pipeline2 = pipeline2.AddingStage(std::make_shared( + LessThanExpr({std::make_shared("address.zip"), + SharedConstant(Value(90000LL))}))); EXPECT_THAT(RunPipeline(pipeline2, documents), ElementsAre(doc2)); RealtimePipeline pipeline3 = StartPipeline("/users"); - pipeline3 = pipeline3.AddingStage(std::make_shared(LtExpr( + pipeline3 = pipeline3.AddingStage(std::make_shared(LessThanExpr( {std::make_shared("address.zip"), SharedConstant(Value(0LL))}))); EXPECT_THAT(RunPipeline(pipeline3, documents), IsEmpty()); RealtimePipeline pipeline4 = StartPipeline("/users"); - pipeline4 = pipeline4.AddingStage( - std::make_shared(NeqExpr({std::make_shared("address.zip"), - SharedConstant(Value(10011LL))}))); + pipeline4 = pipeline4.AddingStage(std::make_shared( + NotEqualExpr({std::make_shared("address.zip"), + SharedConstant(Value(10011LL))}))); EXPECT_THAT(RunPipeline(pipeline4, documents), ElementsAre(doc1, doc3)); } @@ -474,8 +474,8 @@ TEST_F(NestedPropertiesPipelineTest, QuotedNestedPropertyFilterNested) { RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("address.city"), - SharedConstant(Value("San Francisco"))}))); + EqualExpr({std::make_shared("address.city"), + SharedConstant(Value("San Francisco"))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc2)); } @@ -491,8 +491,8 @@ TEST_F(NestedPropertiesPipelineTest, QuotedNestedPropertyFilterQuotedNested) { RealtimePipeline pipeline = StartPipeline("/users"); // Use FieldPath constructor for field names containing dots pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared(FieldPath({"address.city"})), - SharedConstant(Value("San Francisco"))}))); + EqualExpr({std::make_shared(FieldPath({"address.city"})), + SharedConstant(Value("San Francisco"))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc1)); } diff --git a/Firestore/core/test/unit/core/pipeline/null_semantics_test.cc b/Firestore/core/test/unit/core/pipeline/null_semantics_test.cc index c04d0a9594e..d55e1e3d12c 100644 --- a/Firestore/core/test/unit/core/pipeline/null_semantics_test.cc +++ b/Firestore/core/test/unit/core/pipeline/null_semantics_test.cc @@ -66,16 +66,16 @@ using testutil::ArrayContainsAllExpr; using testutil::ArrayContainsAnyExpr; using testutil::ArrayContainsExpr; using testutil::EqAnyExpr; -using testutil::EqExpr; -using testutil::GteExpr; -using testutil::GtExpr; +using testutil::EqualExpr; +using testutil::GreaterThanExpr; +using testutil::GreaterThanOrEqualExpr; using testutil::IsErrorExpr; // Add using for IsErrorExpr using testutil::IsNanExpr; using testutil::IsNullExpr; -using testutil::LteExpr; -using testutil::LtExpr; -using testutil::NeqExpr; +using testutil::LessThanExpr; +using testutil::LessThanOrEqualExpr; using testutil::NotEqAnyExpr; +using testutil::NotEqualExpr; using testutil::NotExpr; using testutil::OrExpr; using testutil::XorExpr; @@ -166,7 +166,7 @@ TEST_F(NullSemanticsPipelineTest, WhereEqConstantAsNull) { RealtimePipeline pipeline = StartPipeline("/users"); // Equality filters never match null or missing fields. - pipeline = pipeline.AddingStage(std::make_shared(EqExpr( + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( {std::make_shared("score"), SharedConstant(Value(nullptr))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); @@ -183,7 +183,7 @@ TEST_F(NullSemanticsPipelineTest, WhereEqFieldAsNull) { RealtimePipeline pipeline = StartPipeline("/users"); // Equality filters never match null or missing fields, even against other // fields. - pipeline = pipeline.AddingStage(std::make_shared(EqExpr( + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( {std::make_shared("score"), std::make_shared("rank")}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); @@ -203,8 +203,8 @@ TEST_F(NullSemanticsPipelineTest, WhereEqSegmentField) { RealtimePipeline pipeline = StartPipeline("/users"); // Equality filters never match null or missing fields. pipeline = pipeline.AddingStage( - std::make_shared(EqExpr({std::make_shared("score.bonus"), - SharedConstant(Value(nullptr))}))); + std::make_shared(EqualExpr({std::make_shared("score.bonus"), + SharedConstant(Value(nullptr))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -228,10 +228,10 @@ TEST_F(NullSemanticsPipelineTest, WhereEqSingleFieldAndSegmentField) { RealtimePipeline pipeline = StartPipeline("/users"); // Equality filters never match null or missing fields. pipeline = pipeline.AddingStage(std::make_shared( - AndExpr({EqExpr({std::make_shared("score.bonus"), - SharedConstant(Value(nullptr))}), - EqExpr({std::make_shared("rank"), - SharedConstant(Value(nullptr))})}))); + AndExpr({EqualExpr({std::make_shared("score.bonus"), + SharedConstant(Value(nullptr))}), + EqualExpr({std::make_shared("rank"), + SharedConstant(Value(nullptr))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -250,8 +250,8 @@ TEST_F(NullSemanticsPipelineTest, WhereEqNullInArray) { RealtimePipeline pipeline = StartPipeline("/k"); // Equality filters never match null values, even within arrays. pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("foo"), - SharedConstant(Value(Array(Value(nullptr))))}))); + EqualExpr({std::make_shared("foo"), + SharedConstant(Value(Array(Value(nullptr))))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -275,8 +275,8 @@ TEST_F(NullSemanticsPipelineTest, WhereEqNullOtherInArray) { RealtimePipeline pipeline = StartPipeline("/k"); // Equality filters never match null values, even within arrays. pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("foo"), - SharedConstant(Value(Array(Value(1.0), Value(nullptr))))}))); + EqualExpr({std::make_shared("foo"), + SharedConstant(Value(Array(Value(1.0), Value(nullptr))))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -294,11 +294,11 @@ TEST_F(NullSemanticsPipelineTest, WhereEqNullNanInArray) { RealtimePipeline pipeline = StartPipeline("/k"); // Equality filters never match null or NaN values, even within arrays. - pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("foo"), - SharedConstant(Value( - Array(Value(nullptr), - Value(std::numeric_limits::quiet_NaN()))))}))); + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("foo"), + SharedConstant( + Value(Array(Value(nullptr), + Value(std::numeric_limits::quiet_NaN()))))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -313,7 +313,7 @@ TEST_F(NullSemanticsPipelineTest, WhereEqNullInMap) { RealtimePipeline pipeline = StartPipeline("/k"); // Equality filters never match null values, even within maps. - pipeline = pipeline.AddingStage(std::make_shared(EqExpr( + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Map("a", nullptr))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); @@ -333,8 +333,8 @@ TEST_F(NullSemanticsPipelineTest, WhereEqNullOtherInMap) { RealtimePipeline pipeline = StartPipeline("/k"); // Equality filters never match null values, even within maps. pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("foo"), - SharedConstant(Map("a", 1.0, "b", nullptr))}))); + EqualExpr({std::make_shared("foo"), + SharedConstant(Map("a", 1.0, "b", nullptr))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -349,10 +349,10 @@ TEST_F(NullSemanticsPipelineTest, WhereEqNullNanInMap) { RealtimePipeline pipeline = StartPipeline("/k"); // Equality filters never match null or NaN values, even within maps. - pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("foo"), - SharedConstant(Map("a", nullptr, "b", - std::numeric_limits::quiet_NaN()))}))); + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("foo"), + SharedConstant(Map("a", nullptr, "b", + std::numeric_limits::quiet_NaN()))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -382,8 +382,8 @@ TEST_F(NullSemanticsPipelineTest, WhereEqMapWithNullArray) { RealtimePipeline pipeline = StartPipeline("/k"); // Equality filters never match null values, even within nested arrays/maps. pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("foo"), - SharedConstant(Map("a", Value(Array(Value(nullptr)))))}))); + EqualExpr({std::make_shared("foo"), + SharedConstant(Map("a", Value(Array(Value(nullptr)))))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -417,7 +417,7 @@ TEST_F(NullSemanticsPipelineTest, WhereEqMapWithNullOtherArray) { RealtimePipeline pipeline = StartPipeline("/k"); // Equality filters never match null values, even within nested arrays/maps. - pipeline = pipeline.AddingStage(std::make_shared(EqExpr( + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Map("a", Value(Array(Value(1.0), Value(nullptr)))))}))); @@ -449,7 +449,7 @@ TEST_F(NullSemanticsPipelineTest, WhereEqMapWithNullNanArray) { RealtimePipeline pipeline = StartPipeline("/k"); // Equality filters never match null or NaN values, even within nested // arrays/maps. - pipeline = pipeline.AddingStage(std::make_shared(EqExpr( + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Map( "a", @@ -466,10 +466,11 @@ TEST_F(NullSemanticsPipelineTest, WhereCompositeConditionWithNull) { RealtimePipeline pipeline = StartPipeline("/users"); // Equality filters never match null values. - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {EqExpr({std::make_shared("score"), SharedConstant(Value(42LL))}), - EqExpr({std::make_shared("rank"), - SharedConstant(Value(nullptr))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({EqualExpr({std::make_shared("score"), + SharedConstant(Value(42LL))}), + EqualExpr({std::make_shared("rank"), + SharedConstant(Value(nullptr))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -660,7 +661,7 @@ TEST_F(NullSemanticsPipelineTest, WhereNeqConstantAsNull) { RealtimePipeline pipeline = StartPipeline("/users"); // != null is not a supported query. - pipeline = pipeline.AddingStage(std::make_shared(NeqExpr( + pipeline = pipeline.AddingStage(std::make_shared(NotEqualExpr( {std::make_shared("score"), SharedConstant(Value(nullptr))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); @@ -676,7 +677,7 @@ TEST_F(NullSemanticsPipelineTest, WhereNeqFieldAsNull) { RealtimePipeline pipeline = StartPipeline("/users"); // != null is not a supported query, even against fields. - pipeline = pipeline.AddingStage(std::make_shared(NeqExpr( + pipeline = pipeline.AddingStage(std::make_shared(NotEqualExpr( {std::make_shared("score"), std::make_shared("rank")}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); @@ -696,8 +697,8 @@ TEST_F(NullSemanticsPipelineTest, WhereNeqNullInArray) { RealtimePipeline pipeline = StartPipeline("/k"); // != [null] is not a supported query. pipeline = pipeline.AddingStage(std::make_shared( - NeqExpr({std::make_shared("foo"), - SharedConstant(Value(Array(Value(nullptr))))}))); + NotEqualExpr({std::make_shared("foo"), + SharedConstant(Value(Array(Value(nullptr))))}))); // Based on TS result, this seems to match documents where 'foo' is not // exactly `[null]`. This behavior might differ in C++ SDK. Assuming it @@ -723,9 +724,9 @@ TEST_F(NullSemanticsPipelineTest, WhereNeqNullOtherInArray) { RealtimePipeline pipeline = StartPipeline("/k"); // != [1.0, null] is not a supported query. - pipeline = pipeline.AddingStage(std::make_shared( - NeqExpr({std::make_shared("foo"), - SharedConstant(Value(Array(Value(1.0), Value(nullptr))))}))); + pipeline = pipeline.AddingStage(std::make_shared(NotEqualExpr( + {std::make_shared("foo"), + SharedConstant(Value(Array(Value(1.0), Value(nullptr))))}))); // Based on TS result. EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc1)); @@ -744,11 +745,11 @@ TEST_F(NullSemanticsPipelineTest, WhereNeqNullNanInArray) { RealtimePipeline pipeline = StartPipeline("/k"); // != [null, NaN] is not a supported query. - pipeline = pipeline.AddingStage(std::make_shared( - NeqExpr({std::make_shared("foo"), - SharedConstant(Value( - Array(Value(nullptr), - Value(std::numeric_limits::quiet_NaN()))))}))); + pipeline = pipeline.AddingStage(std::make_shared(NotEqualExpr( + {std::make_shared("foo"), + SharedConstant( + Value(Array(Value(nullptr), + Value(std::numeric_limits::quiet_NaN()))))}))); // Based on TS result. EXPECT_THAT( @@ -775,7 +776,7 @@ TEST_F(NullSemanticsPipelineTest, WhereNeqNullInMap) { RealtimePipeline pipeline = StartPipeline("/k"); // != {a: null} is not a supported query. - pipeline = pipeline.AddingStage(std::make_shared(NeqExpr( + pipeline = pipeline.AddingStage(std::make_shared(NotEqualExpr( {std::make_shared("foo"), SharedConstant(Map("a", nullptr))}))); // Based on TS result. @@ -797,8 +798,8 @@ TEST_F(NullSemanticsPipelineTest, WhereNeqNullOtherInMap) { RealtimePipeline pipeline = StartPipeline("/k"); // != {a: 1.0, b: null} is not a supported query. pipeline = pipeline.AddingStage(std::make_shared( - NeqExpr({std::make_shared("foo"), - SharedConstant(Map("a", 1.0, "b", nullptr))}))); + NotEqualExpr({std::make_shared("foo"), + SharedConstant(Map("a", 1.0, "b", nullptr))}))); // Based on TS result. EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc1)); @@ -814,7 +815,7 @@ TEST_F(NullSemanticsPipelineTest, WhereNeqNullNanInMap) { RealtimePipeline pipeline = StartPipeline("/k"); // != {a: null, b: NaN} is not a supported query. - pipeline = pipeline.AddingStage(std::make_shared(NeqExpr( + pipeline = pipeline.AddingStage(std::make_shared(NotEqualExpr( {std::make_shared("foo"), SharedConstant(Map("a", nullptr, "b", std::numeric_limits::quiet_NaN()))}))); @@ -858,7 +859,7 @@ TEST_F(NullSemanticsPipelineTest, WhereGt) { RealtimePipeline pipeline = StartPipeline("users"); // > null is not supported. - pipeline = pipeline.AddingStage(std::make_shared(GtExpr( + pipeline = pipeline.AddingStage(std::make_shared(GreaterThanExpr( {std::make_shared("score"), SharedConstant(Value(nullptr))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); @@ -875,8 +876,9 @@ TEST_F(NullSemanticsPipelineTest, WhereGte) { RealtimePipeline pipeline = StartPipeline("users"); // >= null is not supported. - pipeline = pipeline.AddingStage(std::make_shared(GteExpr( - {std::make_shared("score"), SharedConstant(Value(nullptr))}))); + pipeline = + pipeline.AddingStage(std::make_shared(GreaterThanOrEqualExpr( + {std::make_shared("score"), SharedConstant(Value(nullptr))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -892,7 +894,7 @@ TEST_F(NullSemanticsPipelineTest, WhereLt) { RealtimePipeline pipeline = StartPipeline("users"); // < null is not supported. - pipeline = pipeline.AddingStage(std::make_shared(LtExpr( + pipeline = pipeline.AddingStage(std::make_shared(LessThanExpr( {std::make_shared("score"), SharedConstant(Value(nullptr))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); @@ -909,7 +911,7 @@ TEST_F(NullSemanticsPipelineTest, WhereLte) { RealtimePipeline pipeline = StartPipeline("users"); // <= null is not supported. - pipeline = pipeline.AddingStage(std::make_shared(LteExpr( + pipeline = pipeline.AddingStage(std::make_shared(LessThanOrEqualExpr( {std::make_shared("score"), SharedConstant(Value(nullptr))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); @@ -930,8 +932,9 @@ TEST_F(NullSemanticsPipelineTest, WhereAnd) { RealtimePipeline pipeline = StartPipeline("k"); // Need explicit boolean comparison pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {EqExpr({std::make_shared("a"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("b"), SharedConstant(Value(true))})}))); + {EqualExpr({std::make_shared("a"), SharedConstant(Value(true))}), + EqualExpr( + {std::make_shared("b"), SharedConstant(Value(true))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc4)); } @@ -951,8 +954,9 @@ TEST_F(NullSemanticsPipelineTest, WhereIsNullAnd) { RealtimePipeline pipeline = StartPipeline("k"); // Need explicit boolean comparison pipeline = pipeline.AddingStage(std::make_shared(IsNullExpr(AndExpr( - {EqExpr({std::make_shared("a"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("b"), SharedConstant(Value(true))})})))); + {EqualExpr({std::make_shared("a"), SharedConstant(Value(true))}), + EqualExpr( + {std::make_shared("b"), SharedConstant(Value(true))})})))); // Expect docs where (a==true AND b==true) evaluates to NULL. // This happens if either a or b is null/missing AND the other is not false. @@ -998,9 +1002,10 @@ TEST_F(NullSemanticsPipelineTest, WhereIsErrorAnd) { // This happens if either a or b is missing. pipeline = pipeline.AddingStage( std::make_shared(IsErrorExpr(AndExpr( // Use IsErrorExpr helper - {EqExpr({std::make_shared("a"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("b"), - SharedConstant(Value(true))})})))); + {EqualExpr( + {std::make_shared("a"), SharedConstant(Value(true))}), + EqualExpr({std::make_shared("b"), + SharedConstant(Value(true))})})))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc2, doc5, doc8)); @@ -1015,8 +1020,9 @@ TEST_F(NullSemanticsPipelineTest, WhereOr) { RealtimePipeline pipeline = StartPipeline("k"); // Need explicit boolean comparison pipeline = pipeline.AddingStage(std::make_shared(OrExpr( - {EqExpr({std::make_shared("a"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("b"), SharedConstant(Value(true))})}))); + {EqualExpr({std::make_shared("a"), SharedConstant(Value(true))}), + EqualExpr( + {std::make_shared("b"), SharedConstant(Value(true))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc1)); } @@ -1036,8 +1042,9 @@ TEST_F(NullSemanticsPipelineTest, WhereIsNullOr) { RealtimePipeline pipeline = StartPipeline("k"); // Need explicit boolean comparison pipeline = pipeline.AddingStage(std::make_shared(IsNullExpr(OrExpr( - {EqExpr({std::make_shared("a"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("b"), SharedConstant(Value(true))})})))); + {EqualExpr({std::make_shared("a"), SharedConstant(Value(true))}), + EqualExpr( + {std::make_shared("b"), SharedConstant(Value(true))})})))); // Expect docs where (a==true OR b==true) evaluates to NULL. // This happens if neither is true AND at least one is null/missing. @@ -1084,9 +1091,10 @@ TEST_F(NullSemanticsPipelineTest, WhereIsErrorOr) { // This happens if either a or b is missing. pipeline = pipeline.AddingStage( std::make_shared(IsErrorExpr(OrExpr( // Use IsErrorExpr helper - {EqExpr({std::make_shared("a"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("b"), - SharedConstant(Value(true))})})))); + {EqualExpr( + {std::make_shared("a"), SharedConstant(Value(true))}), + EqualExpr({std::make_shared("b"), + SharedConstant(Value(true))})})))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc2, doc5, doc8)); @@ -1108,8 +1116,9 @@ TEST_F(NullSemanticsPipelineTest, WhereXor) { RealtimePipeline pipeline = StartPipeline("k"); // Need explicit boolean comparison and assume XorExpr exists pipeline = pipeline.AddingStage(std::make_shared(XorExpr( - {EqExpr({std::make_shared("a"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("b"), SharedConstant(Value(true))})}))); + {EqualExpr({std::make_shared("a"), SharedConstant(Value(true))}), + EqualExpr( + {std::make_shared("b"), SharedConstant(Value(true))})}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc4)); } @@ -1129,8 +1138,9 @@ TEST_F(NullSemanticsPipelineTest, WhereIsNullXor) { RealtimePipeline pipeline = StartPipeline("k"); // Need explicit boolean comparison and assume XorExpr exists pipeline = pipeline.AddingStage(std::make_shared(IsNullExpr(XorExpr( - {EqExpr({std::make_shared("a"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("b"), SharedConstant(Value(true))})})))); + {EqualExpr({std::make_shared("a"), SharedConstant(Value(true))}), + EqualExpr( + {std::make_shared("b"), SharedConstant(Value(true))})})))); // Expect docs where (a==true XOR b==true) evaluates to NULL. // This happens if either operand is null/missing. @@ -1177,9 +1187,10 @@ TEST_F(NullSemanticsPipelineTest, WhereIsErrorXor) { // This happens if either a or b is missing. pipeline = pipeline.AddingStage( std::make_shared(IsErrorExpr(XorExpr( // Use IsErrorExpr helper - {EqExpr({std::make_shared("a"), SharedConstant(Value(true))}), - EqExpr({std::make_shared("b"), - SharedConstant(Value(true))})})))); + {EqualExpr( + {std::make_shared("a"), SharedConstant(Value(true))}), + EqualExpr({std::make_shared("b"), + SharedConstant(Value(true))})})))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc2, doc5, doc8)); @@ -1196,7 +1207,7 @@ TEST_F(NullSemanticsPipelineTest, WhereNot) { RealtimePipeline pipeline = StartPipeline("k"); pipeline = pipeline.AddingStage(std::make_shared(NotExpr( - EqExpr({std::make_shared("a"), SharedConstant(Value(true))})))); + EqualExpr({std::make_shared("a"), SharedConstant(Value(true))})))); // Based on TS result, only doc2 matches. This implies NOT only works if the // inner expression evaluates cleanly to a boolean. Let's adjust expectation @@ -1215,8 +1226,9 @@ TEST_F(NullSemanticsPipelineTest, WhereIsNullNot) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartPipeline("k"); - pipeline = pipeline.AddingStage(std::make_shared(IsNullExpr(NotExpr( - EqExpr({std::make_shared("a"), SharedConstant(Value(true))}))))); + pipeline = + pipeline.AddingStage(std::make_shared(IsNullExpr(NotExpr(EqualExpr( + {std::make_shared("a"), SharedConstant(Value(true))}))))); // Based on TS result, only doc3 matches. This implies NOT(null_operand) // results in null. Let's adjust expectation to match TS. @@ -1243,7 +1255,7 @@ TEST_F(NullSemanticsPipelineTest, WhereIsErrorNot) { // This happens if a is missing. pipeline = pipeline.AddingStage( std::make_shared(IsErrorExpr(NotExpr( // Use IsErrorExpr helper - EqExpr( + EqualExpr( {std::make_shared("a"), SharedConstant(Value(true))}))))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc4)); diff --git a/Firestore/core/test/unit/core/pipeline/number_semantics_test.cc b/Firestore/core/test/unit/core/pipeline/number_semantics_test.cc index cf05c027088..2f2aff0ead5 100644 --- a/Firestore/core/test/unit/core/pipeline/number_semantics_test.cc +++ b/Firestore/core/test/unit/core/pipeline/number_semantics_test.cc @@ -66,15 +66,15 @@ using testutil::ArrayContainsAllExpr; using testutil::ArrayContainsAnyExpr; using testutil::ArrayContainsExpr; using testutil::EqAnyExpr; -using testutil::EqExpr; -using testutil::GteExpr; -using testutil::GtExpr; +using testutil::EqualExpr; +using testutil::GreaterThanExpr; +using testutil::GreaterThanOrEqualExpr; using testutil::IsNanExpr; using testutil::IsNullExpr; -using testutil::LteExpr; -using testutil::LtExpr; -using testutil::NeqExpr; +using testutil::LessThanExpr; +using testutil::LessThanOrEqualExpr; using testutil::NotEqAnyExpr; +using testutil::NotEqualExpr; using testutil::NotExpr; using testutil::OrExpr; using testutil::XorExpr; @@ -101,8 +101,8 @@ TEST_F(NumberSemanticsPipelineTest, ZeroNegativeDoubleZero) { RealtimePipeline pipeline = StartPipeline("/users"); // Assuming /users based on keys // Firestore treats 0, -0, 0.0, -0.0 as equal. - pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("score"), SharedConstant(Value(-0.0))}))); + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("score"), SharedConstant(Value(-0.0))}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc1, doc2, doc3, doc4)); @@ -117,8 +117,8 @@ TEST_F(NumberSemanticsPipelineTest, ZeroNegativeIntegerZero) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4, doc5}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("score"), SharedConstant(Value(-0LL))}))); + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("score"), SharedConstant(Value(-0LL))}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc1, doc2, doc3, doc4)); @@ -133,8 +133,8 @@ TEST_F(NumberSemanticsPipelineTest, ZeroPositiveDoubleZero) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4, doc5}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("score"), SharedConstant(Value(0.0))}))); + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("score"), SharedConstant(Value(0.0))}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc1, doc2, doc3, doc4)); @@ -149,8 +149,8 @@ TEST_F(NumberSemanticsPipelineTest, ZeroPositiveIntegerZero) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4, doc5}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("score"), SharedConstant(Value(0LL))}))); + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("score"), SharedConstant(Value(0LL))}))); EXPECT_THAT(RunPipeline(pipeline, documents), UnorderedElementsAre(doc1, doc2, doc3, doc4)); @@ -166,7 +166,7 @@ TEST_F(NumberSemanticsPipelineTest, EqualNan) { RealtimePipeline pipeline = StartPipeline("/users"); // NaN is not equal to anything, including NaN. - pipeline = pipeline.AddingStage(std::make_shared(EqExpr( + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( {std::make_shared("age"), SharedConstant(Value(std::numeric_limits::quiet_NaN()))}))); @@ -183,7 +183,7 @@ TEST_F(NumberSemanticsPipelineTest, LessThanNan) { RealtimePipeline pipeline = StartPipeline("/users"); // Comparisons with NaN are always false. - pipeline = pipeline.AddingStage(std::make_shared(LtExpr( + pipeline = pipeline.AddingStage(std::make_shared(LessThanExpr( {std::make_shared("age"), SharedConstant(Value(std::numeric_limits::quiet_NaN()))}))); @@ -200,7 +200,7 @@ TEST_F(NumberSemanticsPipelineTest, LessThanEqualNan) { RealtimePipeline pipeline = StartPipeline("/users"); // Comparisons with NaN are always false. - pipeline = pipeline.AddingStage(std::make_shared(LteExpr( + pipeline = pipeline.AddingStage(std::make_shared(LessThanOrEqualExpr( {std::make_shared("age"), SharedConstant(Value(std::numeric_limits::quiet_NaN()))}))); @@ -217,9 +217,10 @@ TEST_F(NumberSemanticsPipelineTest, GreaterThanEqualNan) { RealtimePipeline pipeline = StartPipeline("/users"); // Comparisons with NaN are always false. - pipeline = pipeline.AddingStage(std::make_shared(GteExpr( - {std::make_shared("age"), - SharedConstant(Value(std::numeric_limits::quiet_NaN()))}))); + pipeline = + pipeline.AddingStage(std::make_shared(GreaterThanOrEqualExpr( + {std::make_shared("age"), + SharedConstant(Value(std::numeric_limits::quiet_NaN()))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } @@ -234,7 +235,7 @@ TEST_F(NumberSemanticsPipelineTest, GreaterThanNan) { RealtimePipeline pipeline = StartPipeline("/users"); // Comparisons with NaN are always false. - pipeline = pipeline.AddingStage(std::make_shared(GtExpr( + pipeline = pipeline.AddingStage(std::make_shared(GreaterThanExpr( {std::make_shared("age"), SharedConstant(Value(std::numeric_limits::quiet_NaN()))}))); @@ -251,7 +252,7 @@ TEST_F(NumberSemanticsPipelineTest, NotEqualNan) { RealtimePipeline pipeline = StartPipeline("/users"); // != NaN is always true (as NaN != NaN). - pipeline = pipeline.AddingStage(std::make_shared(NeqExpr( + pipeline = pipeline.AddingStage(std::make_shared(NotEqualExpr( {std::make_shared("age"), SharedConstant(Value(std::numeric_limits::quiet_NaN()))}))); @@ -388,10 +389,10 @@ TEST_F(NumberSemanticsPipelineTest, ArrayWithNan) { RealtimePipeline pipeline = StartPipeline("/k"); // Equality filters never match NaN values, even within arrays. - pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("foo"), - SharedConstant(Value( - Array(Value(std::numeric_limits::quiet_NaN()))))}))); + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("foo"), + SharedConstant( + Value(Array(Value(std::numeric_limits::quiet_NaN()))))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre()); } diff --git a/Firestore/core/test/unit/core/pipeline/sort_test.cc b/Firestore/core/test/unit/core/pipeline/sort_test.cc index 3802324eb29..9de47dec73e 100644 --- a/Firestore/core/test/unit/core/pipeline/sort_test.cc +++ b/Firestore/core/test/unit/core/pipeline/sort_test.cc @@ -66,9 +66,9 @@ using testutil::Value; // Expression helpers using testutil::AddExpr; using testutil::AndExpr; -using testutil::EqExpr; +using testutil::EqualExpr; using testutil::ExistsExpr; -using testutil::GtExpr; +using testutil::GreaterThanExpr; using testutil::NotExpr; using testutil::RegexMatchExpr; @@ -147,8 +147,8 @@ TEST_F(SortPipelineTest, SingleResultAscendingImplicitExists) { auto doc1 = Doc("users/a", 1000, Map("name", "alice", "age", 10LL)); PipelineInputOutputVector documents = {doc1}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("age"), SharedConstant(Value(10LL))}))); + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("age"), SharedConstant(Value(10LL))}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("age"), Ordering::Direction::ASCENDING)})); @@ -181,8 +181,8 @@ TEST_F(SortPipelineTest, SingleResultDescendingImplicitExists) { auto doc1 = Doc("users/a", 1000, Map("name", "alice", "age", 10LL)); PipelineInputOutputVector documents = {doc1}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("age"), SharedConstant(Value(10LL))}))); + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("age"), SharedConstant(Value(10LL))}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("age"), Ordering::Direction::DESCENDING)})); @@ -230,8 +230,8 @@ TEST_F(SortPipelineTest, MultipleResultsAmbiguousOrderImplicitExists) { auto doc5 = Doc("users/e", 1000, Map("name", "eric", "age", 10.0)); PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4, doc5}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - GtExpr({std::make_shared("age"), SharedConstant(Value(0.0))}))); + pipeline = pipeline.AddingStage(std::make_shared(GreaterThanExpr( + {std::make_shared("age"), SharedConstant(Value(0.0))}))); pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("age"), Ordering::Direction::DESCENDING)})); @@ -308,8 +308,8 @@ TEST_F(SortPipelineTest, MultipleResultsFullOrderImplicitExists) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4, doc5}; RealtimePipeline pipeline = StartPipeline("/users"); pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("age"), - std::make_shared("age")}))); // Implicit exists age + EqualExpr({std::make_shared("age"), + std::make_shared("age")}))); // Implicit exists age pipeline = pipeline.AddingStage(std::make_shared( RegexMatchExpr(std::make_shared("name"), SharedConstant(Value(".*"))))); // Implicit exists name diff --git a/Firestore/core/test/unit/core/pipeline/unicode_test.cc b/Firestore/core/test/unit/core/pipeline/unicode_test.cc index 4828a2a23cc..41b76568a69 100644 --- a/Firestore/core/test/unit/core/pipeline/unicode_test.cc +++ b/Firestore/core/test/unit/core/pipeline/unicode_test.cc @@ -66,11 +66,11 @@ using testutil::Value; // Expression helpers using testutil::AndExpr; using testutil::Constant; // Renamed from ConstantExpr -using testutil::EqExpr; -using testutil::GteExpr; -using testutil::GtExpr; -using testutil::LteExpr; -using testutil::LtExpr; +using testutil::EqualExpr; +using testutil::GreaterThanExpr; +using testutil::GreaterThanOrEqualExpr; +using testutil::LessThanExpr; +using testutil::LessThanOrEqualExpr; // Test Fixture for Unicode Pipeline tests class UnicodePipelineTest : public ::testing::Test { @@ -111,10 +111,11 @@ TEST_F(UnicodePipelineTest, UnicodeSurrogates) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline = StartDatabasePipeline(); pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {LteExpr({std::make_shared("str"), - SharedConstant("🄟")}), // Renamed from ConstantExpr - GteExpr({std::make_shared("str"), - SharedConstant("P")})}))); // Renamed from ConstantExpr + {LessThanOrEqualExpr({std::make_shared("str"), + SharedConstant("🄟")}), // Renamed from ConstantExpr + GreaterThanOrEqualExpr( + {std::make_shared("str"), + SharedConstant("P")})}))); // Renamed from ConstantExpr pipeline = pipeline.AddingStage( std::make_shared(std::vector{Ordering( std::make_unique("str"), Ordering::Direction::ASCENDING)})); diff --git a/Firestore/core/test/unit/core/pipeline/where_test.cc b/Firestore/core/test/unit/core/pipeline/where_test.cc index f6753d29475..a50cf1ecacd 100644 --- a/Firestore/core/test/unit/core/pipeline/where_test.cc +++ b/Firestore/core/test/unit/core/pipeline/where_test.cc @@ -70,16 +70,16 @@ using testutil::ArrayContainsAnyExpr; using testutil::ArrayContainsExpr; using testutil::DivideExpr; using testutil::EqAnyExpr; -using testutil::EqExpr; +using testutil::EqualExpr; using testutil::ExistsExpr; -using testutil::GteExpr; -using testutil::GtExpr; +using testutil::GreaterThanExpr; +using testutil::GreaterThanOrEqualExpr; using testutil::IsNanExpr; using testutil::IsNullExpr; -using testutil::LteExpr; -using testutil::LtExpr; +using testutil::LessThanExpr; +using testutil::LessThanOrEqualExpr; // using testutil::NeqAnyExpr; // Not used -using testutil::NeqExpr; +using testutil::NotEqualExpr; using testutil::NotExpr; using testutil::OrExpr; using testutil::RegexMatchExpr; // For 'like' @@ -105,8 +105,9 @@ class WherePipelineTest : public ::testing::Test { TEST_F(WherePipelineTest, EmptyDatabaseReturnsNoResults) { PipelineInputOutputVector documents = {}; RealtimePipeline pipeline = StartDatabasePipeline(); - pipeline = pipeline.AddingStage(std::make_shared( - GteExpr({std::make_shared("age"), SharedConstant(Value(10LL))}))); + pipeline = + pipeline.AddingStage(std::make_shared(GreaterThanOrEqualExpr( + {std::make_shared("age"), SharedConstant(Value(10LL))}))); EXPECT_THAT(RunPipeline(pipeline, documents), IsEmpty()); } @@ -120,10 +121,11 @@ TEST_F(WherePipelineTest, DuplicateConditions) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4, doc5}; RealtimePipeline pipeline = StartDatabasePipeline(); - pipeline = pipeline.AddingStage(std::make_shared(AndExpr( - {GteExpr({std::make_shared("age"), SharedConstant(Value(10.0))}), - GteExpr( - {std::make_shared("age"), SharedConstant(Value(20.0))})}))); + pipeline = pipeline.AddingStage(std::make_shared( + AndExpr({GreaterThanOrEqualExpr({std::make_shared("age"), + SharedConstant(Value(10.0))}), + GreaterThanOrEqualExpr({std::make_shared("age"), + SharedConstant(Value(20.0))})}))); // Note: TS test expected [doc1, doc2, doc3]. Let's re-evaluate based on C++ // types. age >= 10.0 AND age >= 20.0 => age >= 20.0 Matches: doc1 (75.5), @@ -138,12 +140,12 @@ TEST_F(WherePipelineTest, LogicalEquivalentConditionEqual) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline1 = StartDatabasePipeline(); - pipeline1 = pipeline1.AddingStage(std::make_shared( - EqExpr({std::make_shared("age"), SharedConstant(Value(25.0))}))); + pipeline1 = pipeline1.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("age"), SharedConstant(Value(25.0))}))); RealtimePipeline pipeline2 = StartDatabasePipeline(); - pipeline2 = pipeline2.AddingStage(std::make_shared( - EqExpr({SharedConstant(Value(25.0)), std::make_shared("age")}))); + pipeline2 = pipeline2.AddingStage(std::make_shared(EqualExpr( + {SharedConstant(Value(25.0)), std::make_shared("age")}))); auto result1 = RunPipeline(pipeline1, documents); auto result2 = RunPipeline(pipeline2, documents); @@ -159,16 +161,18 @@ TEST_F(WherePipelineTest, LogicalEquivalentConditionAnd) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline1 = StartDatabasePipeline(); - pipeline1 = pipeline1.AddingStage(std::make_shared(AndExpr( - {GtExpr({std::make_shared("age"), SharedConstant(Value(10.0))}), - LtExpr( - {std::make_shared("age"), SharedConstant(Value(70.0))})}))); + pipeline1 = pipeline1.AddingStage(std::make_shared( + AndExpr({GreaterThanExpr({std::make_shared("age"), + SharedConstant(Value(10.0))}), + LessThanExpr({std::make_shared("age"), + SharedConstant(Value(70.0))})}))); RealtimePipeline pipeline2 = StartDatabasePipeline(); - pipeline2 = pipeline2.AddingStage(std::make_shared(AndExpr( - {LtExpr({std::make_shared("age"), SharedConstant(Value(70.0))}), - GtExpr( - {std::make_shared("age"), SharedConstant(Value(10.0))})}))); + pipeline2 = pipeline2.AddingStage(std::make_shared( + AndExpr({LessThanExpr({std::make_shared("age"), + SharedConstant(Value(70.0))}), + GreaterThanExpr({std::make_shared("age"), + SharedConstant(Value(10.0))})}))); auto result1 = RunPipeline(pipeline1, documents); auto result2 = RunPipeline(pipeline2, documents); @@ -185,16 +189,18 @@ TEST_F(WherePipelineTest, LogicalEquivalentConditionOr) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; RealtimePipeline pipeline1 = StartDatabasePipeline(); - pipeline1 = pipeline1.AddingStage(std::make_shared(OrExpr( - {LtExpr({std::make_shared("age"), SharedConstant(Value(10.0))}), - GtExpr( - {std::make_shared("age"), SharedConstant(Value(80.0))})}))); + pipeline1 = pipeline1.AddingStage(std::make_shared( + OrExpr({LessThanExpr({std::make_shared("age"), + SharedConstant(Value(10.0))}), + GreaterThanExpr({std::make_shared("age"), + SharedConstant(Value(80.0))})}))); RealtimePipeline pipeline2 = StartDatabasePipeline(); - pipeline2 = pipeline2.AddingStage(std::make_shared(OrExpr( - {GtExpr({std::make_shared("age"), SharedConstant(Value(80.0))}), - LtExpr( - {std::make_shared("age"), SharedConstant(Value(10.0))})}))); + pipeline2 = pipeline2.AddingStage(std::make_shared( + OrExpr({GreaterThanExpr({std::make_shared("age"), + SharedConstant(Value(80.0))}), + LessThanExpr({std::make_shared("age"), + SharedConstant(Value(10.0))})}))); auto result1 = RunPipeline(pipeline1, documents); auto result2 = RunPipeline(pipeline2, documents); @@ -239,10 +245,12 @@ TEST_F(WherePipelineTest, RepeatedStages) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4, doc5}; RealtimePipeline pipeline = StartDatabasePipeline(); - pipeline = pipeline.AddingStage(std::make_shared( - GteExpr({std::make_shared("age"), SharedConstant(Value(10.0))}))); - pipeline = pipeline.AddingStage(std::make_shared( - GteExpr({std::make_shared("age"), SharedConstant(Value(20.0))}))); + pipeline = + pipeline.AddingStage(std::make_shared(GreaterThanOrEqualExpr( + {std::make_shared("age"), SharedConstant(Value(10.0))}))); + pipeline = + pipeline.AddingStage(std::make_shared(GreaterThanOrEqualExpr( + {std::make_shared("age"), SharedConstant(Value(20.0))}))); // age >= 10.0 THEN age >= 20.0 => age >= 20.0 // Matches: doc1 (75.5), doc2 (25.0), doc3 (100.0) @@ -260,9 +268,9 @@ TEST_F(WherePipelineTest, CompositeEqualities) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4, doc5}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("age"), SharedConstant(Value(75LL))}))); - pipeline = pipeline.AddingStage(std::make_shared(EqExpr( + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("age"), SharedConstant(Value(75LL))}))); + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( {std::make_shared("height"), SharedConstant(Value(55LL))}))); EXPECT_THAT(RunPipeline(pipeline, documents), ElementsAre(doc3)); @@ -277,9 +285,9 @@ TEST_F(WherePipelineTest, CompositeInequalities) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4, doc5}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - GtExpr({std::make_shared("age"), SharedConstant(Value(50LL))}))); - pipeline = pipeline.AddingStage(std::make_shared(LtExpr( + pipeline = pipeline.AddingStage(std::make_shared(GreaterThanExpr( + {std::make_shared("age"), SharedConstant(Value(50LL))}))); + pipeline = pipeline.AddingStage(std::make_shared(LessThanExpr( {std::make_shared("height"), SharedConstant(Value(75LL))}))); // age > 50 AND height < 75 @@ -337,9 +345,9 @@ TEST_F(WherePipelineTest, CompositeMixed) { PipelineInputOutputVector documents = {doc1, doc2, doc3, doc4, doc5}; RealtimePipeline pipeline = StartPipeline("/users"); - pipeline = pipeline.AddingStage(std::make_shared( - EqExpr({std::make_shared("age"), SharedConstant(Value(75LL))}))); - pipeline = pipeline.AddingStage(std::make_shared(GtExpr( + pipeline = pipeline.AddingStage(std::make_shared(EqualExpr( + {std::make_shared("age"), SharedConstant(Value(75LL))}))); + pipeline = pipeline.AddingStage(std::make_shared(GreaterThanExpr( {std::make_shared("height"), SharedConstant(Value(45LL))}))); pipeline = pipeline.AddingStage(std::make_shared( RegexMatchExpr(std::make_shared("last"), @@ -610,9 +618,9 @@ TEST_F(WherePipelineTest, AndExpressionLogicallyEquivalentToSeparatedStages) { PipelineInputOutputVector documents = {doc1, doc2, doc3}; auto equalityArgument1 = - EqExpr({std::make_shared("a"), SharedConstant(Value(1LL))}); + EqualExpr({std::make_shared("a"), SharedConstant(Value(1LL))}); auto equalityArgument2 = - EqExpr({std::make_shared("b"), SharedConstant(Value(2LL))}); + EqualExpr({std::make_shared("b"), SharedConstant(Value(2LL))}); // Combined AND RealtimePipeline pipeline_and_1 = StartDatabasePipeline(); diff --git a/Firestore/core/test/unit/core/pipeline_util_test.cc b/Firestore/core/test/unit/core/pipeline_util_test.cc index c944a842337..b6a9aa1abee 100644 --- a/Firestore/core/test/unit/core/pipeline_util_test.cc +++ b/Firestore/core/test/unit/core/pipeline_util_test.cc @@ -63,18 +63,18 @@ api::RealtimePipeline StartPipeline( api::RealtimePipeline TestPipeline(int id) { auto pipeline = StartPipeline("coll"); if (id == 1) { - pipeline = pipeline.AddingStage( - std::make_shared(testutil::NotExpr(testutil::GtExpr( + pipeline = pipeline.AddingStage(std::make_shared( + testutil::NotExpr(testutil::GreaterThanExpr( {std::make_shared("score"), testutil::SharedConstant(testutil::Value(90LL))})))); } else if (id == 2) { pipeline = pipeline.AddingStage( - std::make_shared(testutil::NotExpr(testutil::LtExpr( + std::make_shared(testutil::NotExpr(testutil::LessThanExpr( {std::make_shared("score"), testutil::SharedConstant(testutil::Value(90LL))})))); } else if (id == 3) { // Same as id 1 - pipeline = pipeline.AddingStage( - std::make_shared(testutil::NotExpr(testutil::GtExpr( + pipeline = pipeline.AddingStage(std::make_shared( + testutil::NotExpr(testutil::GreaterThanExpr( {std::make_shared("score"), testutil::SharedConstant(testutil::Value(90LL))})))); } diff --git a/Firestore/core/test/unit/local/local_serializer_test.cc b/Firestore/core/test/unit/local/local_serializer_test.cc index 577830efe42..e3e884f73e3 100644 --- a/Firestore/core/test/unit/local/local_serializer_test.cc +++ b/Firestore/core/test/unit/local/local_serializer_test.cc @@ -734,8 +734,8 @@ TEST_F(LocalSerializerTest, EncodesTargetDataWithPipeline) { // Construct the pipeline auto ppl = StartPipeline("rooms"); ppl = ppl.AddingStage(std::make_shared( - testutil::EqExpr({std::make_shared("name"), - testutil::SharedConstant("testroom")}))); + testutil::EqualExpr({std::make_shared("name"), + testutil::SharedConstant("testroom")}))); api::Ordering ordering(std::make_unique("age"), api::Ordering::DESCENDING); ppl = ppl.AddingStage( @@ -772,12 +772,12 @@ TEST_F(LocalSerializerTest, EncodesTargetDataWithPipeline) { stage1_arg1->set_reference_value("/rooms"); } - // Stage 2: Where(EqExpr(Field("name"), Value("testroom"))) + // Stage 2: Where(EqualExpr(Field("name"), Value("testroom"))) { google::firestore::v1::Pipeline_Stage* stage2_proto = pipeline_proto_obj->add_stages(); // Changed type stage2_proto->set_name("where"); - v1::Value* stage2_arg1_expr = stage2_proto->add_args(); // The EqExpr + v1::Value* stage2_arg1_expr = stage2_proto->add_args(); // The EqualExpr v1::Function* eq_func = stage2_arg1_expr->mutable_function_value(); eq_func->set_name("eq"); diff --git a/Firestore/core/test/unit/local/query_engine_test.cc b/Firestore/core/test/unit/local/query_engine_test.cc index 168a4f9f0aa..ff7b53bf9a1 100644 --- a/Firestore/core/test/unit/local/query_engine_test.cc +++ b/Firestore/core/test/unit/local/query_engine_test.cc @@ -1082,10 +1082,11 @@ TEST_P(QueryEngineTest, HandlesServerTimestampEstimate) { auto pipeline = api::RealtimePipeline( {std::make_shared("coll")}, TestSerializer()); - pipeline = pipeline.AddingStage(std::make_shared( - testutil::GtExpr({testutil::TimestampToUnixMillisExpr( - {std::make_shared("timestamp")}), - testutil::SharedConstant(testutil::Value(1000))}))); + pipeline = pipeline.AddingStage( + std::make_shared(testutil::GreaterThanExpr( + {testutil::TimestampToUnixMillisExpr( + {std::make_shared("timestamp")}), + testutil::SharedConstant(testutil::Value(1000))}))); DocumentSet result1 = ExpectFullCollectionScan( [&] { return RunPipeline(pipeline, kMissingLastLimboFreeSnapshot); }); @@ -1118,9 +1119,10 @@ TEST_P(QueryEngineTest, HandlesServerTimestampPrevious) { auto pipeline = api::RealtimePipeline( {std::make_shared("coll")}, TestSerializer()); - pipeline = pipeline.AddingStage(std::make_shared( - testutil::EqExpr({std::make_shared("matches"), - testutil::SharedConstant(testutil::Value(true))}))); + pipeline = + pipeline.AddingStage(std::make_shared(testutil::EqualExpr( + {std::make_shared("matches"), + testutil::SharedConstant(testutil::Value(true))}))); DocumentSet result1 = ExpectFullCollectionScan( [&] { return RunPipeline(pipeline, kMissingLastLimboFreeSnapshot); }); diff --git a/Firestore/core/test/unit/testutil/expression_test_util.h b/Firestore/core/test/unit/testutil/expression_test_util.h index 3386c03d2fb..6d53307a030 100644 --- a/Firestore/core/test/unit/testutil/expression_test_util.h +++ b/Firestore/core/test/unit/testutil/expression_test_util.h @@ -211,46 +211,49 @@ inline std::shared_ptr TimestampAddExpr(std::shared_ptr timestamp, // --- Comparison Expression Helpers --- -inline std::shared_ptr EqExpr( +inline std::shared_ptr EqualExpr( std::initializer_list> params) { - HARD_ASSERT(params.size() == 2, "EqExpr requires exactly 2 parameters"); + HARD_ASSERT(params.size() == 2, "EqualExpr requires exactly 2 parameters"); return std::make_shared( - "eq", std::vector>(params)); + "equal", std::vector>(params)); } -inline std::shared_ptr NeqExpr( +inline std::shared_ptr NotEqualExpr( std::initializer_list> params) { - HARD_ASSERT(params.size() == 2, "NeqExpr requires exactly 2 parameters"); + HARD_ASSERT(params.size() == 2, "NotEqualExpr requires exactly 2 parameters"); return std::make_shared( - "neq", std::vector>(params)); + "not_equal", std::vector>(params)); } -inline std::shared_ptr LtExpr( +inline std::shared_ptr LessThanExpr( std::initializer_list> params) { - HARD_ASSERT(params.size() == 2, "LtExpr requires exactly 2 parameters"); + HARD_ASSERT(params.size() == 2, "LessThanExpr requires exactly 2 parameters"); return std::make_shared( - "lt", std::vector>(params)); + "less_than", std::vector>(params)); } -inline std::shared_ptr LteExpr( +inline std::shared_ptr LessThanOrEqualExpr( std::initializer_list> params) { - HARD_ASSERT(params.size() == 2, "LteExpr requires exactly 2 parameters"); + HARD_ASSERT(params.size() == 2, + "LessThanOrEqualExpr requires exactly 2 parameters"); return std::make_shared( - "lte", std::vector>(params)); + "less_than_or_equal", std::vector>(params)); } -inline std::shared_ptr GtExpr( +inline std::shared_ptr GreaterThanExpr( std::initializer_list> params) { - HARD_ASSERT(params.size() == 2, "GtExpr requires exactly 2 parameters"); + HARD_ASSERT(params.size() == 2, + "GreaterThanExpr requires exactly 2 parameters"); return std::make_shared( - "gt", std::vector>(params)); + "greater_than", std::vector>(params)); } -inline std::shared_ptr GteExpr( +inline std::shared_ptr GreaterThanOrEqualExpr( std::initializer_list> params) { - HARD_ASSERT(params.size() == 2, "GteExpr requires exactly 2 parameters"); + HARD_ASSERT(params.size() == 2, + "GreaterThanOrEqualExpr requires exactly 2 parameters"); return std::make_shared( - "gte", std::vector>(params)); + "greater_than_or_equal", std::vector>(params)); } // --- Array Expression Helpers --- @@ -350,14 +353,14 @@ inline std::shared_ptr IsErrorExpr(std::shared_ptr operand) { "is_error", std::vector>{std::move(operand)}); } -inline std::shared_ptr LogicalMaxExpr( +inline std::shared_ptr MaximumExpr( std::vector> operands) { - return std::make_shared("logical_maximum", std::move(operands)); + return std::make_shared("maximum", std::move(operands)); } -inline std::shared_ptr LogicalMinExpr( +inline std::shared_ptr MinimumExpr( std::vector> operands) { - return std::make_shared("logical_minimum", std::move(operands)); + return std::make_shared("minimum", std::move(operands)); } // --- Debugging Expression Helpers --- @@ -669,9 +672,9 @@ inline std::shared_ptr ToUpperExpr(std::shared_ptr operand) { "to_upper", std::vector>{std::move(operand)}); } -inline std::shared_ptr ReverseExpr(std::shared_ptr operand) { +inline std::shared_ptr StringReverseExpr(std::shared_ptr operand) { return std::make_shared( - "reverse", std::vector>{std::move(operand)}); + "string_reverse", std::vector>{std::move(operand)}); } inline std::shared_ptr TrimExpr(std::shared_ptr operand) { @@ -700,10 +703,10 @@ inline std::shared_ptr RegexMatchExpr(std::shared_ptr value, std::vector>{std::move(value), std::move(regex)}); } -inline std::shared_ptr StrContainsExpr(std::shared_ptr value, - std::shared_ptr search) { +inline std::shared_ptr StringContainsExpr(std::shared_ptr value, + std::shared_ptr search) { return std::make_shared( - "str_contains", + "string_contains", std::vector>{std::move(value), std::move(search)}); } @@ -721,9 +724,9 @@ inline std::shared_ptr EndsWithExpr(std::shared_ptr value, std::vector>{std::move(value), std::move(suffix)}); } -inline std::shared_ptr StrConcatExpr( +inline std::shared_ptr StringConcatExpr( std::vector> operands) { - return std::make_shared("str_concat", std::move(operands)); + return std::make_shared("string_concat", std::move(operands)); } // --- Vector Expression Helpers --- From f9c2439bcc7e83a341838fe7fac3a970e745645e Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Fri, 21 Nov 2025 15:45:30 -0500 Subject: [PATCH 24/36] fix broken tests --- Firestore/core/src/core/expressions_eval.cc | 20 ++++++++++--------- .../unit/core/pipeline/canonify_eq_test.cc | 16 ++++++++------- .../test/unit/local/local_serializer_test.cc | 2 +- .../test/unit/testutil/expression_test_util.h | 4 ++-- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/Firestore/core/src/core/expressions_eval.cc b/Firestore/core/src/core/expressions_eval.cc index 3b19e1629fd..757172c274c 100644 --- a/Firestore/core/src/core/expressions_eval.cc +++ b/Firestore/core/src/core/expressions_eval.cc @@ -245,9 +245,9 @@ std::unique_ptr FunctionToEvaluable( return std::make_unique(function); } else if (function.name() == "cond") { return std::make_unique(function); - } else if (function.name() == "eq_any") { + } else if (function.name() == "equal_any") { return std::make_unique(function); - } else if (function.name() == "not_eq_any") { + } else if (function.name() == "not_equal_any") { return std::make_unique(function); } else if (function.name() == "is_nan") { return std::make_unique(function); @@ -1292,9 +1292,9 @@ EvaluateResult CoreArrayContains::Evaluate( std::vector> reversed_params( expr_->params().rbegin(), expr_->params().rend()); - auto const eq_any = - CoreEqAny(api::FunctionExpr("eq_any", std::move(reversed_params))); - return eq_any.Evaluate(context, document); + auto const equal_any = + CoreEqAny(api::FunctionExpr("equal_any", std::move(reversed_params))); + return equal_any.Evaluate(context, document); } EvaluateResult CoreArrayContainsAll::Evaluate( @@ -1689,9 +1689,10 @@ EvaluateResult CoreCond::Evaluate( EvaluateResult CoreEqAny::Evaluate( const api::EvaluateContext& context, const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 2, - "eq_any() function requires exactly 2 params (search value and " - "array value)"); + HARD_ASSERT( + expr_->params().size() == 2, + "equal_any() function requires exactly 2 params (search value and " + "array value)"); bool found_null = false; @@ -1762,7 +1763,8 @@ EvaluateResult CoreNotEqAny::Evaluate( "array value)"); CoreNot equivalent(api::FunctionExpr( - "not", {std::make_shared("eq_any", expr_->params())})); + "not", + {std::make_shared("equal_any", expr_->params())})); return equivalent.Evaluate(context, document); } diff --git a/Firestore/core/test/unit/core/pipeline/canonify_eq_test.cc b/Firestore/core/test/unit/core/pipeline/canonify_eq_test.cc index 1b4f4fd7124..14ff272dc02 100644 --- a/Firestore/core/test/unit/core/pipeline/canonify_eq_test.cc +++ b/Firestore/core/test/unit/core/pipeline/canonify_eq_test.cc @@ -122,9 +122,10 @@ TEST_F(CanonifyEqPipelineTest, CanonifySimpleWhere) { p = p.AddingStage(std::make_shared(EqualExpr( {std::make_shared("foo"), SharedConstant(Value(42LL))}))); - EXPECT_EQ(GetPipelineCanonicalId(p), - "collection(test)|where(fn(eq[fld(foo),cst(42)]))|sort(fld(__name__" - ")asc)"); + EXPECT_EQ( + GetPipelineCanonicalId(p), + "collection(test)|where(fn(equal[fld(foo),cst(42)]))|sort(fld(__name__" + ")asc)"); } TEST_F(CanonifyEqPipelineTest, CanonifyMultipleStages) { @@ -135,9 +136,10 @@ TEST_F(CanonifyEqPipelineTest, CanonifyMultipleStages) { p = p.AddingStage(std::make_shared( std::vector{Ordering(std::make_shared("bar"), api::Ordering::Direction::DESCENDING)})); - EXPECT_EQ(GetPipelineCanonicalId(p), - "collection(test)|where(fn(eq[fld(foo),cst(42)]))|sort(fld(__name__" - ")asc)|limit(10)|sort(fld(bar)desc,fld(__name__)asc)"); + EXPECT_EQ( + GetPipelineCanonicalId(p), + "collection(test)|where(fn(equal[fld(foo),cst(42)]))|sort(fld(__name__" + ")asc)|limit(10)|sort(fld(bar)desc,fld(__name__)asc)"); } // TEST_F(CanonifyEqPipelineTest, CanonifyAddFields) { @@ -228,7 +230,7 @@ TEST_F(CanonifyEqPipelineTest, CanonifyCollectionGroupSource) { // Value("b")))))); // // EXPECT_EQ(GetPipelineCanonicalId(p), -// "collection(/foo)|where(fn(eq_any,[fld(bar),list([cst(\"a\"),cst(\"b\")])]))|sort(fld(__name__)asc)"); +// collection(/foo)|where(fn(equal_any,[fld(bar),list([cst("a"),cst("b")])]))|sort(fld(__name__)asc)); // } // =================================================================== diff --git a/Firestore/core/test/unit/local/local_serializer_test.cc b/Firestore/core/test/unit/local/local_serializer_test.cc index e3e884f73e3..83668fdb4e6 100644 --- a/Firestore/core/test/unit/local/local_serializer_test.cc +++ b/Firestore/core/test/unit/local/local_serializer_test.cc @@ -779,7 +779,7 @@ TEST_F(LocalSerializerTest, EncodesTargetDataWithPipeline) { stage2_proto->set_name("where"); v1::Value* stage2_arg1_expr = stage2_proto->add_args(); // The EqualExpr v1::Function* eq_func = stage2_arg1_expr->mutable_function_value(); - eq_func->set_name("eq"); + eq_func->set_name("equal"); v1::Value* eq_arg1_field = eq_func->add_args(); // Field("name") eq_arg1_field->set_field_reference_value("name"); diff --git a/Firestore/core/test/unit/testutil/expression_test_util.h b/Firestore/core/test/unit/testutil/expression_test_util.h index 6d53307a030..616fbd64df8 100644 --- a/Firestore/core/test/unit/testutil/expression_test_util.h +++ b/Firestore/core/test/unit/testutil/expression_test_util.h @@ -317,7 +317,7 @@ inline std::shared_ptr EqAnyExpr(std::shared_ptr search, std::vector> operands; operands.push_back(std::move(search)); operands.push_back(std::move(values)); - return std::make_shared("eq_any", std::move(operands)); + return std::make_shared("equal_any", std::move(operands)); } inline std::shared_ptr NotEqAnyExpr(std::shared_ptr search, @@ -325,7 +325,7 @@ inline std::shared_ptr NotEqAnyExpr(std::shared_ptr search, std::vector> operands; operands.push_back(std::move(search)); operands.push_back(std::move(values)); - return std::make_shared("not_eq_any", std::move(operands)); + return std::make_shared("not_equal_any", std::move(operands)); } inline std::shared_ptr IsNanExpr(std::shared_ptr operand) { From 31b39444fc282b161da38caa5e082d06cd787e37 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Mon, 24 Nov 2025 11:06:22 -0500 Subject: [PATCH 25/36] solve merge error --- .github/workflows/firestore.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/.github/workflows/firestore.yml b/.github/workflows/firestore.yml index 4c3e9726425..b336daec031 100644 --- a/.github/workflows/firestore.yml +++ b/.github/workflows/firestore.yml @@ -518,37 +518,6 @@ jobs: platforms: iOS buildonly_platforms: iOS - check-firestore-internal-public-headers: - needs: check - # Either a scheduled run from public repo, or a pull request with firestore changes. - if: | - (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || - (github.event_name == 'pull_request' && needs.changes.outputs.changed == 'true') - runs-on: macos-14 - steps: - - uses: actions/checkout@v4 - - name: Assert that Firestore and FirestoreInternal have identically named headers. - run: | - fst_dir=Firestore/Source/Public/FirebaseFirestore/ - fst_internal_dir=FirebaseFirestoreInternal/FirebaseFirestore/ - - comparison=$(comm -3 <(ls $fst_dir | sort) <(ls $fst_internal_dir | sort)) - - if [[ -z "$comparison" ]]; then - echo "Success: Directories '$fst_dir' and '$fst_internal_dir' match." - else - echo "Error: Directories '$fst_dir' and '$fst_internal_dir' differ:" - echo "Files only in '$fst_dir':" - # Files in this set do not start with whitespace. Grep for them and a - # dashed prefix for nicer formatting. - echo "$comparison" | grep -v '^\s' | sed 's/^/- /' - echo "Files only in '$fst_internal_dir':" - # Files in this set start with whitespace. Grep for them and a dashed - # prefix for nicer formatting. - echo "$comparison" | grep '^\s' | sed 's/^ /- /' - exit 1 - fi - # TODO: Re-enable either in or after #11706. # spm-source-cron: # # Don't run on private repo. From 4d348f702f15be6148d24ffde1b2a82c52291d7a Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Mon, 24 Nov 2025 14:09:37 -0500 Subject: [PATCH 26/36] expose public API of realtime Pipeline --- .../Firestore.xcodeproj/project.pbxproj | 14 +- .../Swift/Source/PipelineResultChange.swift | 2 +- .../Source/SwiftAPI/Firestore+Pipeline.swift | 2 +- .../SwiftAPI/Pipeline/RealtimePipeline.swift | 8 +- .../Pipeline/RealtimePipelineSource.swift | 47 +- .../Integration/QueryIntegrationTests.swift | 38 ++ .../Integration/RealtimePipelineTests.swift | 633 ++++++++++++++++++ 7 files changed, 729 insertions(+), 15 deletions(-) create mode 100644 Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj index c841ac58da0..5a1dd41c53a 100644 --- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj +++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj @@ -823,6 +823,9 @@ 621D620B28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621D620928F9CE7400D2FA26 /* QueryIntegrationTests.swift */; }; 621D620C28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621D620928F9CE7400D2FA26 /* QueryIntegrationTests.swift */; }; 623AA12C3481646B0715006D /* string_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0EE5300F8233D14025EF0456 /* string_apple_test.mm */; }; + 6271643C2ED4D5F400D2CD1D /* RealtimePipelineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6271643B2ED4D5EE00D2CD1D /* RealtimePipelineTests.swift */; }; + 6271643D2ED4D5F400D2CD1D /* RealtimePipelineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6271643B2ED4D5EE00D2CD1D /* RealtimePipelineTests.swift */; }; + 6271643E2ED4D5F400D2CD1D /* RealtimePipelineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6271643B2ED4D5EE00D2CD1D /* RealtimePipelineTests.swift */; }; 627253FDEC6BB5549FE77F4E /* tree_sorted_map_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 549CCA4D20A36DBB00BCEB75 /* tree_sorted_map_test.cc */; }; 62B1C1100A8C68D94565916C /* document_overlay_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = FFCA39825D9678A03D1845D0 /* document_overlay_cache_test.cc */; }; 62C86789E72E624A27BF6AE5 /* complex_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B32C2DDDEC16F6465317B8AE /* complex_test.cc */; }; @@ -2143,6 +2146,7 @@ 61F72C5520BC48FD001A68CB /* serializer_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = serializer_test.cc; sourceTree = ""; }; 620C1427763BA5D3CCFB5A1F /* BridgingHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = BridgingHeader.h; sourceTree = ""; }; 621D620928F9CE7400D2FA26 /* QueryIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryIntegrationTests.swift; sourceTree = ""; }; + 6271643B2ED4D5EE00D2CD1D /* RealtimePipelineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimePipelineTests.swift; sourceTree = ""; }; 62CF8E2E7611B285B46228FE /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS.release.xcconfig"; sourceTree = ""; }; 62E54B832A9E910A003347C8 /* IndexingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndexingTests.swift; sourceTree = ""; }; 63136A2371C0C013EC7A540C /* target_index_matcher_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = target_index_matcher_test.cc; sourceTree = ""; }; @@ -2499,6 +2503,7 @@ 861684E49DAC993D153E60D0 /* PipelineTests.swift */, 621D620928F9CE7400D2FA26 /* QueryIntegrationTests.swift */, 128F2B002E254E2C0006327E /* QueryToPipelineTests.swift */, + 6271643B2ED4D5EE00D2CD1D /* RealtimePipelineTests.swift */, 4D65F6E69993611D47DC8E7C /* SnapshotListenerSourceTests.swift */, EFF22EA92C5060A4009A369B /* VectorIntegrationTests.swift */, ); @@ -4978,6 +4983,7 @@ 655F8647F57E5F2155DFF7B5 /* PipelineTests.swift in Sources */, 621D620C28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */, 128F2B022E254E2C0006327E /* QueryToPipelineTests.swift in Sources */, + 6271643E2ED4D5F400D2CD1D /* RealtimePipelineTests.swift in Sources */, 1CFBD4563960D8A20C4679A3 /* SnapshotListenerSourceTests.swift in Sources */, EE4C4BE7F93366AE6368EE02 /* TestHelper.swift in Sources */, EFF22EAC2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */, @@ -5012,8 +5018,8 @@ E3E6B368A755D892F937DBF7 /* collection_group_test.cc in Sources */, 064689971747DA312770AB7A /* collection_test.cc in Sources */, 1DB3013C5FC736B519CD65A3 /* common.pb.cc in Sources */, - 99F97B28DA546D42AB14214B /* comparison_test.cc in Sources */, 555161D6DB2DDC8B57F72A70 /* comparison_test.cc in Sources */, + 99F97B28DA546D42AB14214B /* comparison_test.cc in Sources */, BB5F19878EA5A8D9C7276D40 /* complex_test.cc in Sources */, 7394B5C29C6E524C2AF964E6 /* counting_query_engine.cc in Sources */, C02A969BF4BB63ABCB531B4B /* create_noop_connectivity_monitor.cc in Sources */, @@ -5259,6 +5265,7 @@ C8C2B945D84DD98391145F3F /* PipelineTests.swift in Sources */, 621D620B28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */, 128F2B032E254E2C0006327E /* QueryToPipelineTests.swift in Sources */, + 6271643C2ED4D5F400D2CD1D /* RealtimePipelineTests.swift in Sources */, A0BC30D482B0ABD1A3A24CDC /* SnapshotListenerSourceTests.swift in Sources */, A78366DBE0BFDE42474A728A /* TestHelper.swift in Sources */, EFF22EAB2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */, @@ -5293,8 +5300,8 @@ 1CDA0E10BC669276E0EAA1E8 /* collection_group_test.cc in Sources */, C87DF880BADEA1CBF8365700 /* collection_test.cc in Sources */, 1D71CA6BBA1E3433F243188E /* common.pb.cc in Sources */, - 476AE05E0878007DE1BF5460 /* comparison_test.cc in Sources */, 9C86EEDEA131BFD50255EEF1 /* comparison_test.cc in Sources */, + 476AE05E0878007DE1BF5460 /* comparison_test.cc in Sources */, C5434EF8A0C8B79A71F0784C /* complex_test.cc in Sources */, DCD83C545D764FB15FD88B02 /* counting_query_engine.cc in Sources */, ECC433628575AE994C621C54 /* create_noop_connectivity_monitor.cc in Sources */, @@ -5822,6 +5829,7 @@ E04CB0D580980748D5DC453F /* PipelineTests.swift in Sources */, 621D620A28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */, 128F2B012E254E2C0006327E /* QueryToPipelineTests.swift in Sources */, + 6271643D2ED4D5F400D2CD1D /* RealtimePipelineTests.swift in Sources */, B00F8D1819EE20C45B660940 /* SnapshotListenerSourceTests.swift in Sources */, AD34726BFD3461FF64BBD56D /* TestHelper.swift in Sources */, EFF22EAA2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */, @@ -5856,8 +5864,8 @@ 4A6B1E0B678E31367A55DC17 /* collection_group_test.cc in Sources */, BACA9CDF0F2E926926B5F36F /* collection_test.cc in Sources */, 4C66806697D7BCA730FA3697 /* common.pb.cc in Sources */, - C885C84B7549C860784E4E3C /* comparison_test.cc in Sources */, EC7A44792A5513FBB6F501EE /* comparison_test.cc in Sources */, + C885C84B7549C860784E4E3C /* comparison_test.cc in Sources */, 62C86789E72E624A27BF6AE5 /* complex_test.cc in Sources */, BDF3A6C121F2773BB3A347A7 /* counting_query_engine.cc in Sources */, 1F4930A8366F74288121F627 /* create_noop_connectivity_monitor.cc in Sources */, diff --git a/Firestore/Swift/Source/PipelineResultChange.swift b/Firestore/Swift/Source/PipelineResultChange.swift index 253bb828d5e..6c56e47eb45 100644 --- a/Firestore/Swift/Source/PipelineResultChange.swift +++ b/Firestore/Swift/Source/PipelineResultChange.swift @@ -20,7 +20,7 @@ import Foundation @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) -struct PipelineResultChange: Sendable { +public struct PipelineResultChange: Sendable { public enum ChangeType { case added, modified, removed } diff --git a/Firestore/Swift/Source/SwiftAPI/Firestore+Pipeline.swift b/Firestore/Swift/Source/SwiftAPI/Firestore+Pipeline.swift index 27b6df8a3d4..630bedcaafe 100644 --- a/Firestore/Swift/Source/SwiftAPI/Firestore+Pipeline.swift +++ b/Firestore/Swift/Source/SwiftAPI/Firestore+Pipeline.swift @@ -60,7 +60,7 @@ import Foundation /// /// - Returns: A `RealtimePipelineSource` for building a realtime pipeline. @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) - @nonobjc internal func realtimePipeline() -> RealtimePipelineSource { + @nonobjc func realtimePipeline() -> RealtimePipelineSource { return RealtimePipelineSource(db: self) { stages, db in RealtimePipeline(stages: stages, db: db) } diff --git a/Firestore/Swift/Source/SwiftAPI/Pipeline/RealtimePipeline.swift b/Firestore/Swift/Source/SwiftAPI/Pipeline/RealtimePipeline.swift index 3883eeb70e6..12a1919c7ea 100644 --- a/Firestore/Swift/Source/SwiftAPI/Pipeline/RealtimePipeline.swift +++ b/Firestore/Swift/Source/SwiftAPI/Pipeline/RealtimePipeline.swift @@ -20,10 +20,10 @@ import Foundation @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) -struct PipelineListenOptions: Sendable, Equatable, Hashable { +public struct PipelineListenOptions: Sendable, Equatable, Hashable { /// Defines how to handle server-generated timestamps that are not yet known locally /// during latency compensation. - struct ServerTimestampBehavior: Sendable, Equatable, Hashable { + public struct ServerTimestampBehavior: Sendable, Equatable, Hashable { /// The raw string value for the behavior, used for implementation and hashability. let rawValue: String /// Creates a new behavior with a private raw value. @@ -91,7 +91,7 @@ struct PipelineListenOptions: Sendable, Equatable, Hashable { } @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) -struct RealtimePipeline: @unchecked Sendable { +public struct RealtimePipeline: @unchecked Sendable { private var stages: [Stage] let bridge: RealtimePipelineBridge @@ -103,7 +103,7 @@ struct RealtimePipeline: @unchecked Sendable { bridge = RealtimePipelineBridge(stages: stages.map { $0.bridge }, db: db) } - struct Snapshot: Sendable { + public struct Snapshot: Sendable { /// An array of all the results in the `PipelineSnapshot`. let results_cache: [PipelineResult] diff --git a/Firestore/Swift/Source/SwiftAPI/Pipeline/RealtimePipelineSource.swift b/Firestore/Swift/Source/SwiftAPI/Pipeline/RealtimePipelineSource.swift index 8928b04f2d1..52e92a1c511 100644 --- a/Firestore/Swift/Source/SwiftAPI/Pipeline/RealtimePipelineSource.swift +++ b/Firestore/Swift/Source/SwiftAPI/Pipeline/RealtimePipelineSource.swift @@ -13,7 +13,7 @@ // limitations under the License. @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) -struct RealtimePipelineSource: @unchecked Sendable { +public struct RealtimePipelineSource: @unchecked Sendable { let db: Firestore let factory: ([Stage], Firestore) -> RealtimePipeline @@ -22,27 +22,62 @@ struct RealtimePipelineSource: @unchecked Sendable { self.factory = factory } - func collection(_ path: String) -> RealtimePipeline { + public func collection(_ path: String) -> RealtimePipeline { return factory([CollectionSource(collection: db.collection(path), db: db)], db) } - func collection(_ coll: CollectionReference) -> RealtimePipeline { + public func collection(_ coll: CollectionReference) -> RealtimePipeline { return factory([CollectionSource(collection: coll, db: db)], db) } - func collectionGroup(_ collectionId: String) -> RealtimePipeline { + public func collectionGroup(_ collectionId: String) -> RealtimePipeline { return factory( [CollectionGroupSource(collectionId: collectionId)], db ) } - func documents(_ docs: [DocumentReference]) -> RealtimePipeline { + public func documents(_ docs: [DocumentReference]) -> RealtimePipeline { return factory([DocumentsSource(docs: docs, db: db)], db) } - func documents(_ paths: [String]) -> RealtimePipeline { + public func documents(_ paths: [String]) -> RealtimePipeline { let docs = paths.map { db.document($0) } return factory([DocumentsSource(docs: docs, db: db)], db) } + + /// Creates a `RealtimePipeline` from an existing `Query`. + /// + /// This allows you to convert a standard Firestore query into a pipeline, which can then be + /// further modified with additional pipeline stages. + /// + /// - Parameter query: The `Query` to convert into a pipeline. + /// - Returns: A `RealtimePipeline` that is equivalent to the given query. + public func create(from query: Query) -> RealtimePipeline { + let stageBridges = PipelineBridge.createStageBridges(from: query) + let stages: [Stage] = stageBridges.map { bridge in + switch bridge.name { + case "collection": + return CollectionSource( + bridge: bridge as! CollectionSourceStageBridge, + db: query.firestore + ) + case "collection_group": + return CollectionGroupSource(bridge: bridge as! CollectionGroupSourceStageBridge) + case "documents": + return DocumentsSource(bridge: bridge as! DocumentsSourceStageBridge, db: query.firestore) + case "where": + return Where(bridge: bridge as! WhereStageBridge) + case "limit": + return Limit(bridge: bridge as! LimitStageBridge) + case "sort": + return Sort(bridge: bridge as! SortStageBridge) + case "offset": + return Offset(bridge: bridge as! OffsetStageBridge) + default: + fatalError("Unknown stage type \(bridge.name)") + } + } + return factory(stages, db) + } } diff --git a/Firestore/Swift/Tests/Integration/QueryIntegrationTests.swift b/Firestore/Swift/Tests/Integration/QueryIntegrationTests.swift index e5257c7860c..d17c58f14bc 100644 --- a/Firestore/Swift/Tests/Integration/QueryIntegrationTests.swift +++ b/Firestore/Swift/Tests/Integration/QueryIntegrationTests.swift @@ -332,3 +332,41 @@ class QueryIntegrationTests: FSTIntegrationTestCase { ) } } + +class QueryAsPipelineIntegrationTests: QueryIntegrationTests { + override class var isRunningPipeline: Bool { + return true + } + + override func check(_ coll: CollectionReference, query: Query, + matchesResult expectedKeys: [String]) async throws { + let collPipeline = coll.firestore.realtimePipeline().create(from: coll) + var collIterator = collPipeline.snapshotStream().makeAsyncIterator() + var _ = try await collIterator.next() + + let pipeline = query.firestore.realtimePipeline().create(from: query) + + var cacheIterator = pipeline.snapshotStream(options: .init(source: .cache)).makeAsyncIterator() + let cacheSnapshot = try await cacheIterator.next() + let cacheResultIds = cacheSnapshot?.results().map { $0.id } + + var serverIterator = pipeline.snapshotStream(options: .init( + includeMetadataChanges: true, + source: .default + )).makeAsyncIterator() + var serverSnapshot = try await serverIterator.next() + if serverSnapshot?.metadata.isFromCache == true { + serverSnapshot = try await serverIterator.next() + } + let serverResultIds = serverSnapshot?.results().map { $0.id } + + var remoteKeysIterator = pipeline.snapshotStream(options: .init(source: .cache)) + .makeAsyncIterator() + let remoteKeysSnapshot = try await remoteKeysIterator.next() + let remoteKeysResultIds = remoteKeysSnapshot?.results().map { $0.id } + + XCTAssertEqual(cacheResultIds, serverResultIds) + XCTAssertEqual(serverResultIds, remoteKeysResultIds) + XCTAssertEqual(remoteKeysResultIds, expectedKeys) + } +} diff --git a/Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift b/Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift new file mode 100644 index 00000000000..57aabb1bfab --- /dev/null +++ b/Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift @@ -0,0 +1,633 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import FirebaseFirestore +import Foundation + +private let bookDocs: [String: [String: Any]] = [ + "book1": [ + "title": "The Hitchhiker's Guide to the Galaxy", + "author": "Douglas Adams", + "genre": "Science Fiction", + "published": 1979, + "rating": 4.2, + "tags": ["comedy", "space", "adventure"], // Array literal + "awards": ["hugo": true, "nebula": false], // Dictionary literal + "nestedField": ["level.1": ["level.2": true]], // Nested dictionary literal + ], + "book2": [ + "title": "Pride and Prejudice", + "author": "Jane Austen", + "genre": "Romance", + "published": 1813, + "rating": 4.5, + "tags": ["classic", "social commentary", "love"], + "awards": ["none": true], + ], + "book3": [ + "title": "One Hundred Years of Solitude", + "author": "Gabriel García Márquez", + "genre": "Magical Realism", + "published": 1967, + "rating": 4.3, + "tags": ["family", "history", "fantasy"], + "awards": ["nobel": true, "nebula": false], + ], + "book4": [ + "title": "The Lord of the Rings", + "author": "J.R.R. Tolkien", + "genre": "Fantasy", + "published": 1954, + "rating": 4.7, + "tags": ["adventure", "magic", "epic"], + "awards": ["hugo": false, "nebula": false], + ], + "book5": [ + "title": "The Handmaid's Tale", + "author": "Margaret Atwood", + "genre": "Dystopian", + "published": 1985, + "rating": 4.1, + "tags": ["feminism", "totalitarianism", "resistance"], + "awards": ["arthur c. clarke": true, "booker prize": false], + ], + "book6": [ + "title": "Crime and Punishment", + "author": "Fyodor Dostoevsky", + "genre": "Psychological Thriller", + "published": 1866, + "rating": 4.3, + "tags": ["philosophy", "crime", "redemption"], + "awards": ["none": true], + ], + "book7": [ + "title": "To Kill a Mockingbird", + "author": "Harper Lee", + "genre": "Southern Gothic", + "published": 1960, + "rating": 4.2, + "tags": ["racism", "injustice", "coming-of-age"], + "awards": ["pulitzer": true], + ], + "book8": [ + "title": "1984", + "author": "George Orwell", + "genre": "Dystopian", + "published": 1949, + "rating": 4.2, + "tags": ["surveillance", "totalitarianism", "propaganda"], + "awards": ["prometheus": true], + ], + "book9": [ + "title": "The Great Gatsby", + "author": "F. Scott Fitzgerald", + "genre": "Modernist", + "published": 1925, + "rating": 4.0, + "tags": ["wealth", "american dream", "love"], + "awards": ["none": true], + ], + "book10": [ + "title": "Dune", + "author": "Frank Herbert", + "genre": "Science Fiction", + "published": 1965, + "rating": 4.6, + "tags": ["politics", "desert", "ecology"], + "awards": ["hugo": true, "nebula": true], + ], +] + +enum RaceResult { + case success(T) + case timedOut +} + +/// Executes an async operation with a timeout. +/// +/// - Parameters: +/// - duration: The maximum time to wait for the operation to complete. +/// - operation: The async operation to perform. +/// - Returns: The result of the operation if it completes within the time limit, otherwise `nil`. +/// - Throws: An error if the `operation` itself throws an error before the timeout. +func withTimeout(nanoSeconds: UInt64, + operation: @escaping @Sendable () async throws -> T) async throws + -> T? { + return try await withThrowingTaskGroup(of: RaceResult.self) { group in + // Add a task for the long-running operation. + group.addTask { + let result = try await operation() + return .success(result) + } + + // Add a task that just sleeps for the duration. + group.addTask { + try await Task.sleep(nanoseconds: nanoSeconds) + return .timedOut + } + + // Await the first result that comes in. + guard let firstResult = try await group.next() else { + // This should not happen if the group has tasks. + return nil + } + + // Once we have a winner, cancel the other task. + // This is CRUCIAL to prevent the losing task from running forever. + group.cancelAll() + + // Switch on the result to return the value or nil. + switch firstResult { + case let .success(value): + return value + case .timedOut: + return nil + } + } +} + +@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) +class RealtimePipelineIntegrationTests: FSTIntegrationTestCase { + override func setUp() { + FSTIntegrationTestCase.switchToEnterpriseMode() + super.setUp() + } + + func testBasicAsyncStream() async throws { + let db = self.db + let collRef = collectionRef() + writeAllDocuments(bookDocs, toCollection: collRef) + + let pipeline = db + .realtimePipeline() + .collection(collRef.path) + .where(Field("rating").greaterThanOrEqual(4.5)) + + let stream = pipeline.snapshotStream() + var iterator = stream.makeAsyncIterator() + + let firstSnapshot = try await iterator.next() + XCTAssertEqual(firstSnapshot!.metadata.isFromCache, true) + XCTAssertEqual(firstSnapshot!.results().count, 3) + XCTAssertEqual(firstSnapshot!.results().first?.get("title") as? String, "Dune") + XCTAssertEqual(firstSnapshot!.results()[1].get("title") as? String, "Pride and Prejudice") + XCTAssertEqual(firstSnapshot!.results()[2].get("title") as? String, "The Lord of the Rings") + + // dropping Dune out of the result set + try await collRef.document("book10").updateData(["rating": 4.4]) + let secondSnapshot = try await iterator.next() + XCTAssertEqual(secondSnapshot!.results().count, 2) + XCTAssertEqual(secondSnapshot!.results()[0].get("title") as? String, "Pride and Prejudice") + XCTAssertEqual(secondSnapshot!.results()[1].get("title") as? String, "The Lord of the Rings") + + // Adding book1 to the result + try await collRef.document("book1").updateData(["rating": 4.7]) + let thirdSnapshot = try await iterator.next() + XCTAssertEqual(thirdSnapshot!.results().count, 3) + XCTAssertEqual( + thirdSnapshot!.results()[0].get("title") as? String, + "The Hitchhiker's Guide to the Galaxy" + ) + + // Adding book1 to the result + try await collRef.document("book2").delete() + let fourthSnapshot = try await iterator.next() + XCTAssertEqual(fourthSnapshot!.results().count, 2) + XCTAssertEqual( + fourthSnapshot!.results()[0].get("title") as? String, + "The Hitchhiker's Guide to the Galaxy" + ) + XCTAssertEqual(fourthSnapshot!.results()[1].get("title") as? String, "The Lord of the Rings") + } + + func testResultChanges() async throws { + let collRef = collectionRef( + withDocuments: bookDocs + ) + let db = collRef.firestore + + let pipeline = db + .realtimePipeline() + .collection(collRef.path) + .where(Field("rating").greaterThanOrEqual(4.5)) + + let stream = pipeline.snapshotStream() + var iterator = stream.makeAsyncIterator() + + let firstSnapshot = try await iterator.next() + XCTAssertEqual(firstSnapshot!.changes.count, 3) + XCTAssertEqual(firstSnapshot!.changes.first?.result.get("title") as? String, "Dune") + XCTAssertEqual(firstSnapshot!.changes.first?.type, .added) + XCTAssertEqual(firstSnapshot!.changes[1].result.get("title") as? String, "Pride and Prejudice") + XCTAssertEqual(firstSnapshot!.changes[1].type, .added) + XCTAssertEqual( + firstSnapshot!.changes[2].result.get("title") as? String, + "The Lord of the Rings" + ) + XCTAssertEqual(firstSnapshot!.changes[2].type, .added) + + // dropping Dune out of the result set + try await collRef.document("book10").updateData(["rating": 4.4]) + let secondSnapshot = try await iterator.next() + XCTAssertEqual(secondSnapshot!.changes.count, 1) + XCTAssertEqual(secondSnapshot!.changes.first?.result.get("title") as? String, "Dune") + XCTAssertEqual(secondSnapshot!.changes.first?.type, .removed) + XCTAssertEqual(secondSnapshot!.changes.first?.oldIndex, 0) + XCTAssertEqual(secondSnapshot!.changes.first?.newIndex, nil) + + // Adding book1 to the result + try await collRef.document("book1").updateData(["rating": 4.7]) + let thirdSnapshot = try await iterator.next() + XCTAssertEqual(thirdSnapshot!.changes.count, 1) + XCTAssertEqual( + thirdSnapshot!.changes[0].result.get("title") as? String, + "The Hitchhiker's Guide to the Galaxy" + ) + XCTAssertEqual(thirdSnapshot!.changes[0].type, .added) + XCTAssertEqual(thirdSnapshot!.changes[0].oldIndex, nil) + XCTAssertEqual(thirdSnapshot!.changes[0].newIndex, 0) + + // Delete book 2 + try await collRef.document("book2").delete() + let fourthSnapshot = try await iterator.next() + XCTAssertEqual(fourthSnapshot!.changes.count, 1) + XCTAssertEqual( + fourthSnapshot!.changes[0].result.get("title") as? String, + "Pride and Prejudice" + ) + XCTAssertEqual(fourthSnapshot!.changes[0].oldIndex, 1) + XCTAssertEqual(fourthSnapshot!.changes[0].newIndex, nil) + } + + func testCanListenToCache() async throws { + let db = self.db + let collRef = collectionRef() + writeAllDocuments(bookDocs, toCollection: collRef) + + let pipeline = db + .realtimePipeline() + .collection(collRef.path) + .where(Field("rating").greaterThanOrEqual(4.5)) + + let stream = pipeline.snapshotStream( + options: PipelineListenOptions(includeMetadataChanges: true, source: .cache) + ) + + actor IteratorWrapper { + var iterator: AsyncThrowingStream.Iterator + init(_ iterator: AsyncThrowingStream.Iterator) { + self.iterator = iterator + } + + func next() async throws -> RealtimePipeline.Snapshot? { + var localIterator = iterator + defer { iterator = localIterator } + return try await localIterator.next() + } + } + let wrapper = IteratorWrapper(stream.makeAsyncIterator()) + + let firstSnapshot = try await wrapper.next() + XCTAssertEqual(firstSnapshot!.metadata.isFromCache, true) + XCTAssertEqual(firstSnapshot!.results().count, 3) + XCTAssertEqual(firstSnapshot!.results().first?.get("title") as? String, "Dune") + XCTAssertEqual(firstSnapshot!.results()[1].get("title") as? String, "Pride and Prejudice") + XCTAssertEqual(firstSnapshot!.results()[2].get("title") as? String, "The Lord of the Rings") + + disableNetwork() + enableNetwork() + + let duration: UInt64 = 100 * 1_000_000 // 100ms + let result = try await withTimeout(nanoSeconds: duration) { + try await wrapper.next() + } + + XCTAssertNil(result as Any?) + } + + func testCanListenToMetadataOnlyChanges() async throws { + let db = self.db + let collRef = collectionRef() + writeAllDocuments(bookDocs, toCollection: collRef) + + let pipeline = db + .realtimePipeline() + .collection(collRef.path) + .where(Field("rating").greaterThanOrEqual(4.5)) + + let stream = pipeline.snapshotStream( + options: PipelineListenOptions(includeMetadataChanges: true) + ) + var iterator = stream.makeAsyncIterator() + + let firstSnapshot = try await iterator.next() + XCTAssertEqual(firstSnapshot!.metadata.isFromCache, true) + XCTAssertEqual(firstSnapshot!.results().count, 3) + XCTAssertEqual(firstSnapshot!.results().first?.get("title") as? String, "Dune") + XCTAssertEqual(firstSnapshot!.results()[1].get("title") as? String, "Pride and Prejudice") + XCTAssertEqual(firstSnapshot!.results()[2].get("title") as? String, "The Lord of the Rings") + + disableNetwork() + enableNetwork() + + let secondSnapshot = try await iterator.next() + XCTAssertEqual(secondSnapshot!.metadata.isFromCache, false) + XCTAssertEqual(secondSnapshot!.results().count, 3) + XCTAssertEqual(secondSnapshot!.changes.count, 0) + } + + func testCanReadServerTimestampEstimateProperly() async throws { + let db = self.db + let collRef = collectionRef() + writeAllDocuments(bookDocs, toCollection: collRef) + + disableNetwork() + + try await collRef.document("book1").updateData([ + "rating": FieldValue.serverTimestamp(), + ]) + + let stream = db.realtimePipeline().collection(collRef.path) + .where(Field("title").equal("The Hitchhiker's Guide to the Galaxy")) + .snapshotStream(options: PipelineListenOptions(serverTimestamps: .estimate)) + + var iterator = stream.makeAsyncIterator() + + let firstSnapshot = try await iterator.next() + let result = firstSnapshot!.results()[0] + XCTAssertEqual(firstSnapshot!.metadata.isFromCache, true) + XCTAssertNotNil(result.get("rating") as? Timestamp) + XCTAssertEqual(result.get("rating") as? Timestamp, result.data["rating"] as? Timestamp) + let firstChanges = firstSnapshot!.changes + XCTAssertEqual(firstChanges.count, 1) + XCTAssertEqual(firstChanges[0].type, .added) + XCTAssertNotNil(firstChanges[0].result.get("rating") as? Timestamp) + XCTAssertEqual( + firstChanges[0].result.get("rating") as? Timestamp, + result.get("rating") as? Timestamp + ) + + enableNetwork() + + let secondSnapshot = try await iterator.next() + XCTAssertEqual(secondSnapshot!.metadata.isFromCache, false) + XCTAssertNotEqual( + secondSnapshot!.results()[0].get("rating") as? Timestamp, + result.data["rating"] as? Timestamp + ) + let secondChanges = secondSnapshot!.changes + XCTAssertEqual(secondChanges.count, 1) + XCTAssertEqual(secondChanges[0].type, .modified) + XCTAssertNotNil(secondChanges[0].result.get("rating") as? Timestamp) + XCTAssertEqual( + secondChanges[0].result.get("rating") as? Timestamp, + secondSnapshot!.results()[0].get("rating") as? Timestamp + ) + } + + func testCanEvaluateServerTimestampEstimateProperly() async throws { + let db = self.db + let collRef = collectionRef() + writeAllDocuments(bookDocs, toCollection: collRef) + + disableNetwork() + + let now = Constant(Timestamp(date: Date())) + + try await collRef.document("book1").updateData([ + "rating": FieldValue.serverTimestamp(), + ]) + + let stream = db.realtimePipeline().collection(collRef.path) + .where( + Field("rating").timestampAdd(amount: Constant("second"), unit: Constant(1)).greaterThan(now) + ) + .snapshotStream( + options: PipelineListenOptions(serverTimestamps: .estimate, includeMetadataChanges: true) + ) + + var iterator = stream.makeAsyncIterator() + + let firstSnapshot = try await iterator.next() + let result = firstSnapshot!.results()[0] + XCTAssertEqual(firstSnapshot!.metadata.isFromCache, true) + XCTAssertNotNil(result.get("rating") as? Timestamp) + XCTAssertEqual(result.get("rating") as? Timestamp, result.data["rating"] as? Timestamp) + + // TODO(pipeline): Enable this when watch supports timestampAdd + // enableNetwork() + // + // let secondSnapshot = try await iterator.next() + // XCTAssertEqual(secondSnapshot!.metadata.isFromCache, false) + // XCTAssertNotEqual( + // secondSnapshot!.results()[0].get("rating") as? Timestamp, + // result.data["rating"] as? Timestamp + // ) + } + + func testCanReadServerTimestampPreviousProperly() async throws { + let db = self.db + let collRef = collectionRef() + writeAllDocuments(bookDocs, toCollection: collRef) + + disableNetwork() + + try await collRef.document("book1").updateData([ + "rating": FieldValue.serverTimestamp(), + ]) + + let stream = db.realtimePipeline().collection(collRef.path) + .where(Field("title").equal("The Hitchhiker's Guide to the Galaxy")) + .snapshotStream(options: PipelineListenOptions(serverTimestamps: .previous)) + + var iterator = stream.makeAsyncIterator() + + let firstSnapshot = try await iterator.next() + let result = firstSnapshot!.results()[0] + XCTAssertEqual(firstSnapshot!.metadata.isFromCache, true) + XCTAssertNotNil(result.get("rating") as? Double) + XCTAssertEqual(result.get("rating") as! Double, 4.2) + XCTAssertEqual(result.get("rating") as! Double, result.data["rating"] as! Double) + let firstChanges = firstSnapshot!.changes + XCTAssertEqual(firstChanges.count, 1) + XCTAssertEqual(firstChanges[0].type, .added) + XCTAssertEqual(firstChanges[0].result.get("rating") as! Double, 4.2) + + enableNetwork() + + let secondSnapshot = try await iterator.next() + XCTAssertEqual(secondSnapshot!.metadata.isFromCache, false) + XCTAssertNotNil(secondSnapshot!.results()[0].get("rating") as? Timestamp) + let secondChanges = secondSnapshot!.changes + XCTAssertEqual(secondChanges.count, 1) + XCTAssertEqual(secondChanges[0].type, .modified) + XCTAssertNotNil(secondChanges[0].result.get("rating") as? Timestamp) + XCTAssertEqual( + secondChanges[0].result.get("rating") as? Timestamp, + secondSnapshot!.results()[0].get("rating") as? Timestamp + ) + } + + func testCanEvaluateServerTimestampPreviousProperly() async throws { + let db = self.db + let collRef = collectionRef() + writeAllDocuments(bookDocs, toCollection: collRef) + + disableNetwork() + + try await collRef.document("book1").updateData([ + "title": FieldValue.serverTimestamp(), + ]) + + let stream = db.realtimePipeline().collection(collRef.path) + .where(Field("title").equal("The Hitchhiker's Guide to the Galaxy")) + .snapshotStream( + options: PipelineListenOptions(serverTimestamps: .previous) + ) + + var iterator = stream.makeAsyncIterator() + + let firstSnapshot = try await iterator.next() + let result = firstSnapshot!.results()[0] + XCTAssertEqual(firstSnapshot!.metadata.isFromCache, true) + XCTAssertEqual(result.get("title") as? String, "The Hitchhiker's Guide to the Galaxy") + + // TODO(pipeline): Enable this when watch supports timestampAdd + // enableNetwork() + } + + func testCanReadServerTimestampNoneProperly() async throws { + let db = self.db + let collRef = collectionRef() + writeAllDocuments(bookDocs, toCollection: collRef) + + disableNetwork() + + try await collRef.document("book1").updateData([ + "rating": FieldValue.serverTimestamp(), + ]) + + let stream = db.realtimePipeline().collection(collRef.path) + .where(Field("title").equal("The Hitchhiker's Guide to the Galaxy")) + // .none is the default behavior + .snapshotStream() + + var iterator = stream.makeAsyncIterator() + + let firstSnapshot = try await iterator.next() + let result = firstSnapshot!.results()[0] + XCTAssertEqual(firstSnapshot!.metadata.isFromCache, true) + XCTAssertNil(result.get("rating") as? Timestamp) + XCTAssertEqual(result.get("rating") as? Timestamp, result.data["rating"] as? Timestamp) + let firstChanges = firstSnapshot!.changes + XCTAssertEqual(firstChanges.count, 1) + XCTAssertEqual(firstChanges[0].type, .added) + XCTAssertNil(firstChanges[0].result.get("rating") as? Timestamp) + + enableNetwork() + + let secondSnapshot = try await iterator.next() + XCTAssertEqual(secondSnapshot!.metadata.isFromCache, false) + XCTAssertNotNil(secondSnapshot!.results()[0].get("rating") as? Timestamp) + let secondChanges = secondSnapshot!.changes + XCTAssertEqual(secondChanges.count, 1) + XCTAssertEqual(secondChanges[0].type, .modified) + XCTAssertNotNil(secondChanges[0].result.get("rating") as? Timestamp) + XCTAssertEqual( + secondChanges[0].result.get("rating") as? Timestamp, + secondSnapshot!.results()[0].get("rating") as? Timestamp + ) + } + + func testCanEvaluateServerTimestampNoneProperly() async throws { + let db = self.db + let collRef = collectionRef() + writeAllDocuments(bookDocs, toCollection: collRef) + + disableNetwork() + + try await collRef.document("book1").updateData([ + "title": FieldValue.serverTimestamp(), + ]) + + let stream = db.realtimePipeline().collection(collRef.path) + .where(Field("title").equal(Constant.nil)) + .snapshotStream( + ) + + var iterator = stream.makeAsyncIterator() + + let firstSnapshot = try await iterator.next() + let result = firstSnapshot!.results()[0] + XCTAssertEqual(firstSnapshot!.metadata.isFromCache, true) + XCTAssertNil(result.get("title") as? String) + + // TODO(pipeline): Enable this when watch supports timestampAdd + // enableNetwork() + } + + func testSamePipelineWithDifferetnOptions() async throws { + let db = self.db + let collRef = collectionRef() + writeAllDocuments(bookDocs, toCollection: collRef) + + disableNetwork() + + try await collRef.document("book1").updateData([ + "title": FieldValue.serverTimestamp(), + ]) + + let pipeline = db.realtimePipeline().collection(collRef.path) + .where(Field("title").notEqual(Constant.nil)) + .limit(1) + + let stream1 = pipeline + .snapshotStream( + options: PipelineListenOptions(serverTimestamps: .previous) + ) + + var iterator1 = stream1.makeAsyncIterator() + + let firstSnapshot1 = try await iterator1.next() + var result1 = firstSnapshot1!.results()[0] + XCTAssertEqual(firstSnapshot1!.metadata.isFromCache, true) + XCTAssertEqual(result1.get("title") as? String, "The Hitchhiker's Guide to the Galaxy") + + let stream2 = pipeline + .snapshotStream( + options: PipelineListenOptions(serverTimestamps: .estimate) + ) + + var iterator2 = stream2.makeAsyncIterator() + + let firstSnapshot2 = try await iterator2.next() + var result2 = firstSnapshot2!.results()[0] + XCTAssertEqual(firstSnapshot2!.metadata.isFromCache, true) + XCTAssertNotNil(result2.get("title") as? Timestamp) + + enableNetwork() + + let secondSnapshot1 = try await iterator1.next() + result1 = secondSnapshot1!.results()[0] + XCTAssertEqual(secondSnapshot1!.metadata.isFromCache, false) + XCTAssertNotNil(result1.get("title") as? Timestamp) + + let secondSnapshot2 = try await iterator2.next() + result2 = secondSnapshot2!.results()[0] + XCTAssertEqual(secondSnapshot2!.metadata.isFromCache, false) + XCTAssertNotNil(result2.get("title") as? Timestamp) + } +} From 1a267b1f8b65e7cfde57bc49e4ccce06c00cc84d Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Fri, 28 Nov 2025 11:05:55 -0500 Subject: [PATCH 27/36] fix hanging test --- .../Integration/RealtimePipelineTests.swift | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift b/Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift index 57aabb1bfab..df78858175e 100644 --- a/Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift +++ b/Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift @@ -356,9 +356,11 @@ class RealtimePipelineIntegrationTests: FSTIntegrationTestCase { disableNetwork() - try await collRef.document("book1").updateData([ - "rating": FieldValue.serverTimestamp(), - ]) + Task { + try? await collRef.document("book1").updateData([ + "rating": FieldValue.serverTimestamp(), + ]) + } let stream = db.realtimePipeline().collection(collRef.path) .where(Field("title").equal("The Hitchhiker's Guide to the Galaxy")) @@ -406,10 +408,11 @@ class RealtimePipelineIntegrationTests: FSTIntegrationTestCase { disableNetwork() let now = Constant(Timestamp(date: Date())) - - try await collRef.document("book1").updateData([ - "rating": FieldValue.serverTimestamp(), - ]) + Task { + try? await collRef.document("book1").updateData([ + "rating": FieldValue.serverTimestamp(), + ]) + } let stream = db.realtimePipeline().collection(collRef.path) .where( @@ -445,9 +448,11 @@ class RealtimePipelineIntegrationTests: FSTIntegrationTestCase { disableNetwork() - try await collRef.document("book1").updateData([ - "rating": FieldValue.serverTimestamp(), - ]) + Task { + try? await collRef.document("book1").updateData([ + "rating": FieldValue.serverTimestamp(), + ]) + } let stream = db.realtimePipeline().collection(collRef.path) .where(Field("title").equal("The Hitchhiker's Guide to the Galaxy")) @@ -488,9 +493,11 @@ class RealtimePipelineIntegrationTests: FSTIntegrationTestCase { disableNetwork() - try await collRef.document("book1").updateData([ - "title": FieldValue.serverTimestamp(), - ]) + Task { + try? await collRef.document("book1").updateData([ + "title": FieldValue.serverTimestamp(), + ]) + } let stream = db.realtimePipeline().collection(collRef.path) .where(Field("title").equal("The Hitchhiker's Guide to the Galaxy")) @@ -516,9 +523,11 @@ class RealtimePipelineIntegrationTests: FSTIntegrationTestCase { disableNetwork() - try await collRef.document("book1").updateData([ - "rating": FieldValue.serverTimestamp(), - ]) + Task { + try? await collRef.document("book1").updateData([ + "rating": FieldValue.serverTimestamp(), + ]) + } let stream = db.realtimePipeline().collection(collRef.path) .where(Field("title").equal("The Hitchhiker's Guide to the Galaxy")) @@ -559,9 +568,11 @@ class RealtimePipelineIntegrationTests: FSTIntegrationTestCase { disableNetwork() - try await collRef.document("book1").updateData([ - "title": FieldValue.serverTimestamp(), - ]) + Task { + try? await collRef.document("book1").updateData([ + "title": FieldValue.serverTimestamp(), + ]) + } let stream = db.realtimePipeline().collection(collRef.path) .where(Field("title").equal(Constant.nil)) @@ -586,9 +597,11 @@ class RealtimePipelineIntegrationTests: FSTIntegrationTestCase { disableNetwork() - try await collRef.document("book1").updateData([ - "title": FieldValue.serverTimestamp(), - ]) + Task { + try? await collRef.document("book1").updateData([ + "title": FieldValue.serverTimestamp(), + ]) + } let pipeline = db.realtimePipeline().collection(collRef.path) .where(Field("title").notEqual(Constant.nil)) From cf2c71509f9b98772c41a29f09b12ee862c86f6c Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Mon, 1 Dec 2025 11:53:15 -0500 Subject: [PATCH 28/36] separate expression file --- Firestore/core/CMakeLists.txt | 21 + Firestore/core/src/core/expressions_eval.cc | 2532 ----------------- Firestore/core/src/core/expressions_eval.h | 908 +----- .../core/src/core/pipeline/aggregates.cc | 96 + Firestore/core/src/core/pipeline/aggregates.h | 57 + .../core/pipeline/evaluation/arithmetic.cc | 204 ++ .../src/core/pipeline/evaluation/arithmetic.h | 121 + .../src/core/pipeline/evaluation/array.cc | 332 +++ .../core/src/core/pipeline/evaluation/array.h | 96 + .../core/pipeline/evaluation/comparison.cc | 203 ++ .../src/core/pipeline/evaluation/comparison.h | 116 + .../src/core/pipeline/evaluation/logical.cc | 282 ++ .../src/core/pipeline/evaluation/logical.h | 122 + .../core/src/core/pipeline/evaluation/map.cc | 88 + .../core/src/core/pipeline/evaluation/map.h | 44 + .../src/core/pipeline/evaluation/string.cc | 520 ++++ .../src/core/pipeline/evaluation/string.h | 211 ++ .../src/core/pipeline/evaluation/timestamp.cc | 303 ++ .../src/core/pipeline/evaluation/timestamp.h | 157 + .../core/src/core/pipeline/evaluation/type.cc | 136 + .../core/src/core/pipeline/evaluation/type.h | 109 + .../core/src/core/pipeline/evaluation/util.cc | 105 + .../core/src/core/pipeline/evaluation/util.h | 40 + .../core/src/core/pipeline/expression.cc | 279 ++ Firestore/core/src/core/pipeline/expression.h | 155 + 25 files changed, 3807 insertions(+), 3430 deletions(-) delete mode 100644 Firestore/core/src/core/expressions_eval.cc create mode 100644 Firestore/core/src/core/pipeline/aggregates.cc create mode 100644 Firestore/core/src/core/pipeline/aggregates.h create mode 100644 Firestore/core/src/core/pipeline/evaluation/arithmetic.cc create mode 100644 Firestore/core/src/core/pipeline/evaluation/arithmetic.h create mode 100644 Firestore/core/src/core/pipeline/evaluation/array.cc create mode 100644 Firestore/core/src/core/pipeline/evaluation/array.h create mode 100644 Firestore/core/src/core/pipeline/evaluation/comparison.cc create mode 100644 Firestore/core/src/core/pipeline/evaluation/comparison.h create mode 100644 Firestore/core/src/core/pipeline/evaluation/logical.cc create mode 100644 Firestore/core/src/core/pipeline/evaluation/logical.h create mode 100644 Firestore/core/src/core/pipeline/evaluation/map.cc create mode 100644 Firestore/core/src/core/pipeline/evaluation/map.h create mode 100644 Firestore/core/src/core/pipeline/evaluation/string.cc create mode 100644 Firestore/core/src/core/pipeline/evaluation/string.h create mode 100644 Firestore/core/src/core/pipeline/evaluation/timestamp.cc create mode 100644 Firestore/core/src/core/pipeline/evaluation/timestamp.h create mode 100644 Firestore/core/src/core/pipeline/evaluation/type.cc create mode 100644 Firestore/core/src/core/pipeline/evaluation/type.h create mode 100644 Firestore/core/src/core/pipeline/evaluation/util.cc create mode 100644 Firestore/core/src/core/pipeline/evaluation/util.h create mode 100644 Firestore/core/src/core/pipeline/expression.cc create mode 100644 Firestore/core/src/core/pipeline/expression.h diff --git a/Firestore/core/CMakeLists.txt b/Firestore/core/CMakeLists.txt index 90cd4af476c..8971b7cd965 100644 --- a/Firestore/core/CMakeLists.txt +++ b/Firestore/core/CMakeLists.txt @@ -200,6 +200,26 @@ firebase_ios_glob( src/bundle/*.h src/core/*.cc src/core/*.h + src/core/pipeline/*.cc + src/core/pipeline/*.h + src/core/pipeline/evaluation/arithmetic.cc + src/core/pipeline/evaluation/arithmetic.h + src/core/pipeline/evaluation/array.cc + src/core/pipeline/evaluation/array.h + src/core/pipeline/evaluation/comparison.cc + src/core/pipeline/evaluation/comparison.h + src/core/pipeline/evaluation/logical.cc + src/core/pipeline/evaluation/logical.h + src/core/pipeline/evaluation/map.cc + src/core/pipeline/evaluation/map.h + src/core/pipeline/evaluation/string.cc + src/core/pipeline/evaluation/string.h + src/core/pipeline/evaluation/timestamp.cc + src/core/pipeline/evaluation/timestamp.h + src/core/pipeline/evaluation/type.cc + src/core/pipeline/evaluation/type.h + src/core/pipeline/evaluation/util.cc + src/core/pipeline/evaluation/util.h src/credentials/*.cc src/credentials/*.h src/immutable/*.cc @@ -243,6 +263,7 @@ target_compile_definitions( target_include_directories( firestore_core PUBLIC ${PROJECT_SOURCE_DIR}/Firestore/core/include + ${PROJECT_SOURCE_DIR}/Firestore/core/src/core ) # Add the gRPC include directories as SYSTEM directories to silence warnings diff --git a/Firestore/core/src/core/expressions_eval.cc b/Firestore/core/src/core/expressions_eval.cc deleted file mode 100644 index 757172c274c..00000000000 --- a/Firestore/core/src/core/expressions_eval.cc +++ /dev/null @@ -1,2532 +0,0 @@ -/* - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Firestore/core/src/core/expressions_eval.h" - -#include // For std::reverse -#include -#include -#include // Added for std::function -#include // For std::numeric_limits -#include -#include -#include -#include // For std::move -#include // For std::vector - -// Ensure timestamp proto is included -#include "Firestore/core/src/api/expressions.h" -#include "Firestore/core/src/api/stages.h" -#include "Firestore/core/src/model/mutable_document.h" -#include "Firestore/core/src/model/server_timestamp_util.h" -#include "Firestore/core/src/model/value_util.h" // For value helpers like IsArray, DeepClone -#include "Firestore/core/src/nanopb/message.h" // Added for MakeMessage -#include "Firestore/core/src/remote/serializer.h" -#include "Firestore/core/src/util/hard_assert.h" -#include "Firestore/core/src/util/log.h" -#include "absl/strings/ascii.h" // For AsciiStrToLower/ToUpper (if needed later) -#include "absl/strings/match.h" // For StartsWith, EndsWith, StrContains -#include "absl/strings/str_cat.h" // For StrAppend -#include "absl/strings/strip.h" // For StripAsciiWhitespace -#include "absl/types/optional.h" -#include "re2/re2.h" - -namespace firebase { -namespace firestore { -namespace core { - -namespace { - -// Helper functions for safe integer arithmetic with overflow detection. -// Return nullopt on overflow or error (like division by zero). - -absl::optional SafeAdd(int64_t lhs, int64_t rhs) { - int64_t result; -#if defined(__clang__) || defined(__GNUC__) - if (__builtin_add_overflow(lhs, rhs, &result)) { - return absl::nullopt; - } -#else - // Manual check (less efficient, might miss some edge cases on weird - // platforms) - if ((rhs > 0 && lhs > std::numeric_limits::max() - rhs) || - (rhs < 0 && lhs < std::numeric_limits::min() - rhs)) { - return absl::nullopt; - } - result = lhs + rhs; -#endif - return result; -} - -absl::optional SafeSubtract(int64_t lhs, int64_t rhs) { - int64_t result; -#if defined(__clang__) || defined(__GNUC__) - if (__builtin_sub_overflow(lhs, rhs, &result)) { - return absl::nullopt; - } -#else - // Manual check - if ((rhs < 0 && lhs > std::numeric_limits::max() + rhs) || - (rhs > 0 && lhs < std::numeric_limits::min() + rhs)) { - return absl::nullopt; - } - result = lhs - rhs; -#endif - return result; -} - -absl::optional SafeMultiply(int64_t lhs, int64_t rhs) { - int64_t result; -#if defined(__clang__) || defined(__GNUC__) - if (__builtin_mul_overflow(lhs, rhs, &result)) { - return absl::nullopt; - } -#else - // Manual check (simplified, might not cover all edge cases perfectly) - if (lhs != 0 && rhs != 0) { - if (lhs > std::numeric_limits::max() / rhs || - lhs < std::numeric_limits::min() / rhs) { - return absl::nullopt; - } - } - result = lhs * rhs; -#endif - return result; -} - -absl::optional SafeDivide(int64_t lhs, int64_t rhs) { - if (rhs == 0) { - return absl::nullopt; // Division by zero - } - // Check for overflow: INT64_MIN / -1 - if (lhs == std::numeric_limits::min() && rhs == -1) { - return absl::nullopt; - } - return lhs / rhs; -} - -absl::optional SafeMod(int64_t lhs, int64_t rhs) { - if (rhs == 0) { - return absl::nullopt; // Modulo by zero - } - // Check for potential overflow/UB: INT64_MIN % -1 - if (lhs == std::numeric_limits::min() && rhs == -1) { - // The result is 0 on most platforms, but standard allows signal. - // Treat as error for consistency. - return absl::nullopt; - } - return lhs % rhs; -} - -// Helper to create a Value proto from int64_t -nanopb::Message IntValue(int64_t val) { - google_firestore_v1_Value proto; - proto.which_value_type = google_firestore_v1_Value_integer_value_tag; - proto.integer_value = val; - return nanopb::MakeMessage(std::move(proto)); -} - -// Helper to create a Value proto from double -nanopb::Message DoubleValue(double val) { - google_firestore_v1_Value proto; - proto.which_value_type = google_firestore_v1_Value_double_value_tag; - proto.double_value = val; - return nanopb::MakeMessage(std::move(proto)); -} - -} // anonymous namespace - -EvaluateResult::EvaluateResult( - EvaluateResult::ResultType type, - nanopb::Message message) - : value_(std::move(message)), type_(type) { -} - -EvaluateResult EvaluateResult::NewNull() { - return EvaluateResult( - ResultType::kNull, - nanopb::Message(model::MinValue())); -} - -EvaluateResult EvaluateResult::NewValue( - nanopb::Message value) { - if (model::IsNullValue(*value)) { - return EvaluateResult::NewNull(); - } else if (value->which_value_type == - google_firestore_v1_Value_boolean_value_tag) { - return EvaluateResult(ResultType::kBoolean, std::move(value)); - } else if (model::IsInteger(*value)) { - return EvaluateResult(ResultType::kInt, std::move(value)); - } else if (model::IsDouble(*value)) { - return EvaluateResult(ResultType::kDouble, std::move(value)); - } else if (value->which_value_type == - google_firestore_v1_Value_timestamp_value_tag) { - return EvaluateResult(ResultType::kTimestamp, std::move(value)); - } else if (value->which_value_type == - google_firestore_v1_Value_string_value_tag) { - return EvaluateResult(ResultType::kString, std::move(value)); - } else if (value->which_value_type == - google_firestore_v1_Value_bytes_value_tag) { - return EvaluateResult(ResultType::kBytes, std::move(value)); - } else if (value->which_value_type == - google_firestore_v1_Value_reference_value_tag) { - return EvaluateResult(ResultType::kReference, std::move(value)); - } else if (value->which_value_type == - google_firestore_v1_Value_geo_point_value_tag) { - return EvaluateResult(ResultType::kGeoPoint, std::move(value)); - } else if (model::IsArray(*value)) { - return EvaluateResult(ResultType::kArray, std::move(value)); - } else if (model::IsVectorValue(*value)) { - // vector value must be before map value - return EvaluateResult(ResultType::kVector, std::move(value)); - } else if (model::IsMap(*value)) { - return EvaluateResult(ResultType::kMap, std::move(value)); - } else { - return EvaluateResult(ResultType::kError, {}); - } -} - -std::unique_ptr FunctionToEvaluable( - const api::FunctionExpr& function) { - if (function.name() == "equal") { - return std::make_unique(function); - } else if (function.name() == "add") { - return std::make_unique(function); - } else if (function.name() == "subtract") { - return std::make_unique(function); - } else if (function.name() == "multiply") { - return std::make_unique(function); - } else if (function.name() == "divide") { - return std::make_unique(function); - } else if (function.name() == "mod") { - return std::make_unique(function); - } else if (function.name() == "not_equal") { - return std::make_unique(function); - } else if (function.name() == "less_than") { - return std::make_unique(function); - } else if (function.name() == "less_than_or_equal") { - return std::make_unique(function); - } else if (function.name() == "greater_than") { - return std::make_unique(function); - } else if (function.name() == "greater_than_or_equal") { - return std::make_unique(function); - } else if (function.name() == "array_reverse") { // Removed array_concat - return std::make_unique(function); - } else if (function.name() == "array_contains") { - return std::make_unique(function); - } else if (function.name() == "array_contains_all") { - return std::make_unique(function); - } else if (function.name() == "array_contains_any") { - return std::make_unique(function); - } else if (function.name() == "array_length") { - return std::make_unique(function); - } else if (function.name() == "exists") { - return std::make_unique(function); - } else if (function.name() == "not") { - return std::make_unique(function); - } else if (function.name() == "and") { - return std::make_unique(function); - } else if (function.name() == "or") { - return std::make_unique(function); - } else if (function.name() == "xor") { - return std::make_unique(function); - } else if (function.name() == "cond") { - return std::make_unique(function); - } else if (function.name() == "equal_any") { - return std::make_unique(function); - } else if (function.name() == "not_equal_any") { - return std::make_unique(function); - } else if (function.name() == "is_nan") { - return std::make_unique(function); - } else if (function.name() == "is_not_nan") { - return std::make_unique(function); - } else if (function.name() == "is_null") { - return std::make_unique(function); - } else if (function.name() == "is_not_null") { - return std::make_unique(function); - } else if (function.name() == "is_error") { - return std::make_unique(function); - } else if (function.name() == "maximum") { - return std::make_unique(function); - } else if (function.name() == "minimum") { - return std::make_unique(function); - } else if (function.name() == "map_get") { - return std::make_unique(function); - } else if (function.name() == "byte_length") { - return std::make_unique(function); - } else if (function.name() == "char_length") { - return std::make_unique(function); - } else if (function.name() == "string_concat") { - return std::make_unique(function); - } else if (function.name() == "ends_with") { - return std::make_unique(function); - } else if (function.name() == "starts_with") { - return std::make_unique(function); - } else if (function.name() == "string_contains") { - return std::make_unique(function); - } else if (function.name() == "to_lower") { - return std::make_unique(function); - } else if (function.name() == "to_upper") { - return std::make_unique(function); - } else if (function.name() == "trim") { - return std::make_unique(function); - } else if (function.name() == "string_reverse") { - return std::make_unique(function); - } else if (function.name() == "regex_contains") { - return std::make_unique(function); - } else if (function.name() == "regex_match") { - return std::make_unique(function); - } else if (function.name() == "like") { - return std::make_unique(function); - } else if (function.name() == "unix_micros_to_timestamp") { - return std::make_unique(function); - } else if (function.name() == "unix_millis_to_timestamp") { - return std::make_unique(function); - } else if (function.name() == "unix_seconds_to_timestamp") { - return std::make_unique(function); - } else if (function.name() == "timestamp_to_unix_micros") { - return std::make_unique(function); - } else if (function.name() == "timestamp_to_unix_millis") { - return std::make_unique(function); - } else if (function.name() == "timestamp_to_unix_seconds") { - return std::make_unique(function); - } else if (function.name() == "timestamp_add") { - return std::make_unique(function); - } else if (function.name() == "timestamp_sub") { - return std::make_unique(function); - } - - HARD_FAIL("Unsupported function name: %s", function.name()); -} - -namespace { - -nanopb::Message GetServerTimestampValue( - const api::EvaluateContext& context, - const google_firestore_v1_Value& timestamp_sentinel) { - if (context.listen_options().server_timestamp_behavior() == - ListenOptions::ServerTimestampBehavior::kEstimate) { - google_firestore_v1_Value result; - result.which_value_type = google_firestore_v1_Value_timestamp_value_tag; - result.timestamp_value = model::GetLocalWriteTime(timestamp_sentinel); - return nanopb::MakeMessage(result); - } - - if (context.listen_options().server_timestamp_behavior() == - ListenOptions::ServerTimestampBehavior::kPrevious) { - auto result = model::GetPreviousValue(timestamp_sentinel); - if (result.has_value()) { - return model::DeepClone(result.value()); - } - } - - return nanopb::MakeMessage(model::NullValue()); -} - -} // namespace - -EvaluateResult CoreField::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& input) const { - auto* field = dynamic_cast(expr_.get()); - if (field->alias() == model::FieldPath::kDocumentKeyPath) { - google_firestore_v1_Value result; - - result.which_value_type = google_firestore_v1_Value_reference_value_tag; - result.reference_value = context.serializer().EncodeKey(input.key()); - - return EvaluateResult::NewValue(nanopb::MakeMessage(std::move(result))); - } - - if (field->alias() == model::FieldPath::kUpdateTimePath) { - google_firestore_v1_Value result; - - result.which_value_type = google_firestore_v1_Value_timestamp_value_tag; - result.timestamp_value = - context.serializer().EncodeVersion(input.version()); - - return EvaluateResult::NewValue(nanopb::MakeMessage(std::move(result))); - } - - // TODO(pipeline): Add create time support. - - // Return 'UNSET' if the field doesn't exist, otherwise the Value. - const auto& result = input.field(field->field_path()); - if (result.has_value()) { - if (model::IsServerTimestamp(result.value())) { - return EvaluateResult::NewValue( - GetServerTimestampValue(context, result.value())); - } - - // DeepClone the field value to avoid modifying the original. - return EvaluateResult::NewValue(model::DeepClone(result.value())); - } else { - return EvaluateResult::NewUnset(); - } -} - -EvaluateResult CoreConstant::Evaluate(const api::EvaluateContext&, - const model::PipelineInputOutput&) const { - auto* constant = dynamic_cast(expr_.get()); - return EvaluateResult::NewValue(nanopb::MakeMessage(constant->to_proto())); -} - -// --- Comparison Implementations --- - -EvaluateResult ComparisonBase::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 2, - "%s() function requires exactly 2 params", expr_->name()); - - std::unique_ptr left_evaluable = - expr_->params()[0]->ToEvaluable(); - EvaluateResult left = left_evaluable->Evaluate(context, document); - - switch (left.type()) { - case EvaluateResult::ResultType::kError: - case EvaluateResult::ResultType::kUnset: { - return EvaluateResult::NewError(); - } - default: - break; - } - - std::unique_ptr right_evaluable = - expr_->params()[1]->ToEvaluable(); - EvaluateResult right = right_evaluable->Evaluate(context, document); - switch (right.type()) { - case EvaluateResult::ResultType::kError: - case EvaluateResult::ResultType::kUnset: { - return EvaluateResult::NewError(); - } - default: - break; - } - - // Comparisons involving Null propagate Null - if (left.IsNull() || right.IsNull()) { - return EvaluateResult::NewNull(); - } - - // Operands are valid Values, proceed with specific comparison - return CompareToResult(left, right); -} - -EvaluateResult CoreEqual::CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const { - // Type mismatch always results in false for Eq - if (model::GetTypeOrder(*left.value()) != - model::GetTypeOrder(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } - // NaN == anything (including NaN) is false - if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } - - switch (model::StrictEquals(*left.value(), *right.value())) { - case model::StrictEqualsResult::kEq: - return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); - case model::StrictEqualsResult::kNotEq: - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - case model::StrictEqualsResult::kNull: - return EvaluateResult::NewNull(); - } - HARD_FAIL("Unhandled case in switch statement"); -} - -EvaluateResult CoreNotEqual::CompareToResult( - const EvaluateResult& left, const EvaluateResult& right) const { - // NaN != anything (including NaN) is true - if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); - } - // Type mismatch always results in true for Neq - if (model::GetTypeOrder(*left.value()) != - model::GetTypeOrder(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); - } - - switch (model::StrictEquals(*left.value(), *right.value())) { - case model::StrictEqualsResult::kEq: - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - case model::StrictEqualsResult::kNotEq: - return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); - case model::StrictEqualsResult::kNull: - return EvaluateResult::NewNull(); - } - HARD_FAIL("Unhandled case in switch statement"); -} - -EvaluateResult CoreLessThan::CompareToResult( - const EvaluateResult& left, const EvaluateResult& right) const { - // Type mismatch always results in false - if (model::GetTypeOrder(*left.value()) != - model::GetTypeOrder(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } - // NaN compared to anything is false - if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } - - bool result = model::Compare(*left.value(), *right.value()) == - util::ComparisonResult::Ascending; - return EvaluateResult::NewValue( - nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); -} - -EvaluateResult CoreLessThanOrEqual::CompareToResult( - const EvaluateResult& left, const EvaluateResult& right) const { - // Type mismatch always results in false - if (model::GetTypeOrder(*left.value()) != - model::GetTypeOrder(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } - // NaN compared to anything is false - if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } - - // Check for equality first using StrictEquals - if (model::StrictEquals(*left.value(), *right.value()) == - model::StrictEqualsResult::kEq) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); - } - - // If not equal, perform standard comparison - bool result = model::Compare(*left.value(), *right.value()) == - util::ComparisonResult::Ascending; - return EvaluateResult::NewValue( - nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); -} - -EvaluateResult CoreGreaterThan::CompareToResult( - const EvaluateResult& left, const EvaluateResult& right) const { - // Type mismatch always results in false - if (model::GetTypeOrder(*left.value()) != - model::GetTypeOrder(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } - // NaN compared to anything is false - if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } - - bool result = model::Compare(*left.value(), *right.value()) == - util::ComparisonResult::Descending; - return EvaluateResult::NewValue( - nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); -} - -EvaluateResult CoreGreaterThanOrEqual::CompareToResult( - const EvaluateResult& left, const EvaluateResult& right) const { - // Type mismatch always results in false - if (model::GetTypeOrder(*left.value()) != - model::GetTypeOrder(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } - // NaN compared to anything is false - if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } - - // Check for equality first using StrictEquals - if (model::StrictEquals(*left.value(), *right.value()) == - model::StrictEqualsResult::kEq) { - return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); - } - - // If not equal, perform standard comparison - bool result = model::Compare(*left.value(), *right.value()) == - util::ComparisonResult::Descending; - return EvaluateResult::NewValue( - nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); -} - -// --- String Expression Implementations --- - -namespace { - -/** - * @brief Validates a string as UTF-8 and process the Unicode code points. - * - * Iterates through the byte sequence of the input string, performing - * full UTF-8 validation checks: - * - Correct number of continuation bytes. - * - Correct format of continuation bytes (10xxxxxx). - * - No overlong encodings (e.g., encoding '/' as 2 bytes). - * - Decoded code points are within the valid Unicode range - * (U+0000-U+D7FF and U+E000-U+10FFFF), excluding surrogates. - * - * @tparam T The type of the result accumulator. - * @param s The input string (byte sequence) to validate. - * @param result A pointer to the result accumulator, updated by `func`. - * @param func A function `void(T* result, uint32_t code_point, - * absl::string_view utf8_bytes)` called for each valid code point, providing - * the code point and its UTF-8 byte representation. - * @return `true` if the string is valid UTF-8, `false` otherwise. - */ -template -bool ProcessUtf8(const std::string& s, - T* result, - std::function func) { - size_t i = 0; - const size_t len = s.size(); - const unsigned char* data = reinterpret_cast(s.data()); - - while (i < len) { - uint32_t code_point = 0; // To store the decoded code point - int num_bytes = 0; - const unsigned char start_byte = data[i]; - - // 1. Determine expected sequence length and initial code point bits - if ((start_byte & 0x80) == 0) { // 1-byte sequence (ASCII 0xxxxxxx) - num_bytes = 1; - code_point = start_byte; - // Overlong check: Not possible for 1-byte sequences - // Range check: ASCII is always valid (0x00-0x7F) - } else if ((start_byte & 0xE0) == 0xC0) { // 2-byte sequence (110xxxxx) - num_bytes = 2; - code_point = start_byte & 0x1F; // Mask out 110xxxxx - // Overlong check: Must not represent code points < 0x80 - // Also, C0 and C1 are specifically invalid start bytes - if (start_byte < 0xC2) { - return false; // C0, C1 are invalid starts - } - } else if ((start_byte & 0xF0) == 0xE0) { // 3-byte sequence (1110xxxx) - num_bytes = 3; - code_point = start_byte & 0x0F; // Mask out 1110xxxx - } else if ((start_byte & 0xF8) == 0xF0) { // 4-byte sequence (11110xxx) - num_bytes = 4; - code_point = - start_byte & 0x07; // Mask out 11110xxx - // Overlong check: Must not represent code points - // < 0x10000 Range check: Must not represent code - // points > 0x10FFFF F4 90.. BF.. is > 0x10FFFF - if (start_byte > 0xF4) { - return false; - } - } else { - return false; // Invalid start byte (e.g., 10xxxxxx or > F4) - } - - // 2. Check for incomplete sequence - if (i + num_bytes > len) { - return false; // Sequence extends beyond string end - } - - // 3. Check and process continuation bytes (if any) - for (int j = 1; j < num_bytes; ++j) { - const unsigned char continuation_byte = data[i + j]; - if ((continuation_byte & 0xC0) != 0x80) { - return false; // Not a valid continuation byte (10xxxxxx) - } - // Combine bits into the code point - code_point = (code_point << 6) | (continuation_byte & 0x3F); - } - - // 4. Perform Overlong and Range Checks based on the fully decoded - // code_point - if (num_bytes == 2 && code_point < 0x80) { - return false; // Overlong encoding (should have been 1 byte) - } - if (num_bytes == 3 && code_point < 0x800) { - // Specific check for 0xE0 0x80..0x9F .. sequences (overlong) - if (start_byte == 0xE0 && (data[i + 1] & 0xFF) < 0xA0) { - return false; - } - return false; // Overlong encoding (should have been 1 or 2 bytes) - } - if (num_bytes == 4 && code_point < 0x10000) { - // Specific check for 0xF0 0x80..0x8F .. sequences (overlong) - if (start_byte == 0xF0 && (data[i + 1] & 0xFF) < 0x90) { - return false; - } - return false; // Overlong encoding (should have been 1, 2 or 3 bytes) - } - - // Check for surrogates (U+D800 to U+DFFF) - if (code_point >= 0xD800 && code_point <= 0xDFFF) { - return false; - } - - // Check for code points beyond the Unicode maximum (U+10FFFF) - if (code_point > 0x10FFFF) { - // Specific check for 0xF4 90..BF .. sequences (> U+10FFFF) - if (start_byte == 0xF4 && (data[i + 1] & 0xFF) > 0x8F) { - return false; - } - return false; - } - - // 5. If all checks passed, call the function and advance index - absl::string_view utf8_bytes(s.data() + i, num_bytes); - func(result, code_point, utf8_bytes); - i += num_bytes; - } - - return true; // String is valid UTF-8 -} - -// Helper function to convert SQL LIKE patterns to RE2 regex patterns. -// Handles % (matches any sequence of zero or more characters) -// and _ (matches any single character). -// Escapes other regex special characters. -std::string LikeToRegex(const std::string& like_pattern) { - std::string regex_pattern = "^"; // Anchor at the start - for (char c : like_pattern) { - switch (c) { - case '%': - regex_pattern += ".*"; - break; - case '_': - regex_pattern += "."; - break; - // Escape RE2 special characters - case '\\': - case '.': - case '*': - case '+': - case '?': - case '(': - case ')': - case '|': - case '{': - case '}': - case '[': - case ']': - case '^': - case '$': - regex_pattern += '\\'; - regex_pattern += c; - break; - default: - regex_pattern += c; - break; - } - } - regex_pattern += '$'; // Anchor at the end - return regex_pattern; -} - -} // anonymous namespace - -EvaluateResult StringSearchBase::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 2, - "%s() function requires exactly 2 params", expr_->name()); - - bool has_null = false; - EvaluateResult op1 = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - switch (op1.type()) { - case EvaluateResult::ResultType::kString: { - break; - } - case EvaluateResult::ResultType::kNull: { - has_null = true; - break; - } - default: { - return EvaluateResult::NewError(); - } - } - - EvaluateResult op2 = - expr_->params()[1]->ToEvaluable()->Evaluate(context, document); - switch (op2.type()) { - case EvaluateResult::ResultType::kString: { - break; - } - case EvaluateResult::ResultType::kNull: { - has_null = true; - break; - } - default: { - return EvaluateResult::NewError(); - } - } - - // Null propagation - if (has_null) { - return EvaluateResult::NewNull(); - } - - // Both operands are valid strings, perform the specific search - std::string value_str = nanopb::MakeString(op1.value()->string_value); - std::string search_str = nanopb::MakeString(op2.value()->string_value); - - return PerformSearch(value_str, search_str); -} - -EvaluateResult CoreRegexContains::PerformSearch( - const std::string& value, const std::string& search) const { - re2::RE2 re(search); - if (!re.ok()) { - // TODO(wuandy): Log warning about invalid regex? - return EvaluateResult::NewError(); - } - bool result = RE2::PartialMatch(value, re); - return EvaluateResult::NewValue( - nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); -} - -EvaluateResult CoreRegexMatch::PerformSearch(const std::string& value, - const std::string& search) const { - re2::RE2 re(search); - if (!re.ok()) { - // TODO(wuandy): Log warning about invalid regex? - return EvaluateResult::NewError(); - } - bool result = RE2::FullMatch(value, re); - return EvaluateResult::NewValue( - nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); -} - -EvaluateResult CoreLike::PerformSearch(const std::string& value, - const std::string& search) const { - std::string regex_pattern = LikeToRegex(search); - re2::RE2 re(regex_pattern); - // LikeToRegex should ideally produce valid regex, but check anyway. - if (!re.ok()) { - // TODO(wuandy): Log warning about failed LIKE conversion? - return EvaluateResult::NewError(); - } - // LIKE implies matching the entire string - bool result = RE2::FullMatch(value, re); - return EvaluateResult::NewValue( - nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); -} - -EvaluateResult CoreByteLength::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "byte_length() requires exactly 1 param"); - EvaluateResult evaluated = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - - switch (evaluated.type()) { - case EvaluateResult::ResultType::kString: { - const auto str = nanopb::MakeString(evaluated.value()->string_value); - // Validate UTF-8 using the generic function with a no-op lambda - bool dummy_result = false; // Result accumulator not needed here - bool is_valid_utf8 = ProcessUtf8( - str, &dummy_result, - [](bool*, uint32_t, absl::string_view) { /* no-op */ }); - - if (is_valid_utf8) { - return EvaluateResult::NewValue(IntValue(str.size())); - } else { - return EvaluateResult::NewError(); // Invalid UTF-8 - } - } - case EvaluateResult::ResultType::kBytes: { - const size_t len = evaluated.value()->bytes_value == nullptr - ? 0 - : evaluated.value()->bytes_value->size; - return EvaluateResult::NewValue(IntValue(len)); - } - case EvaluateResult::ResultType::kNull: - return EvaluateResult::NewNull(); - default: - return EvaluateResult::NewError(); // Type mismatch or Error/Unset - } -} - -EvaluateResult CoreCharLength::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "char_length() requires exactly 1 param"); - EvaluateResult evaluated = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - - switch (evaluated.type()) { - case EvaluateResult::ResultType::kString: { - const auto str = nanopb::MakeString(evaluated.value()->string_value); - // Count codepoints using the generic function - int char_count = 0; - bool is_valid_utf8 = ProcessUtf8( - str, &char_count, - [](int* count, uint32_t, absl::string_view) { (*count)++; }); - - if (is_valid_utf8) { - return EvaluateResult::NewValue(IntValue(char_count)); - } else { - return EvaluateResult::NewError(); // Invalid UTF-8 - } - } - case EvaluateResult::ResultType::kNull: - return EvaluateResult::NewNull(); - default: - return EvaluateResult::NewError(); // Type mismatch or Error/Unset - } -} - -EvaluateResult CoreStringConcat::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - std::string result_string; - - bool found_null = false; - for (const auto& param : expr_->params()) { - EvaluateResult evaluated = - param->ToEvaluable()->Evaluate(context, document); - switch (evaluated.type()) { - case EvaluateResult::ResultType::kString: { - absl::StrAppend(&result_string, - nanopb::MakeString(evaluated.value()->string_value)); - break; - } - case EvaluateResult::ResultType::kNull: { - found_null = true; - break; - } - default: - return EvaluateResult::NewError(); // Type mismatch or Error/Unset - } - } - - if (found_null) { - return EvaluateResult::NewNull(); - } - - return EvaluateResult::NewValue(model::StringValue(result_string)); -} - -EvaluateResult CoreEndsWith::PerformSearch(const std::string& value, - const std::string& search) const { - // Use absl::EndsWith - bool result = absl::EndsWith(value, search); - return EvaluateResult::NewValue( - nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); -} - -EvaluateResult CoreStartsWith::PerformSearch(const std::string& value, - const std::string& search) const { - // Use absl::StartsWith - bool result = absl::StartsWith(value, search); - return EvaluateResult::NewValue( - nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); -} - -EvaluateResult CoreStringContains::PerformSearch( - const std::string& value, const std::string& search) const { - // Use absl::StrContains - bool result = absl::StrContains(value, search); - return EvaluateResult::NewValue( - nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); -} - -EvaluateResult CoreToLower::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "to_lower() requires exactly 1 param"); - EvaluateResult evaluated = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - - switch (evaluated.type()) { - case EvaluateResult::ResultType::kString: { - std::locale locale{"en_US.UTF-8"}; - std::string str = nanopb::MakeString(evaluated.value()->string_value); - std::transform(str.begin(), str.end(), str.begin(), - [&locale](char c) { return std::tolower(c, locale); }); - return EvaluateResult::NewValue(model::StringValue(str)); - } - case EvaluateResult::ResultType::kNull: - return EvaluateResult::NewNull(); - default: - return EvaluateResult::NewError(); // Type mismatch or Error/Unset - } -} -EvaluateResult CoreToUpper::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "to_upper() requires exactly 1 param"); - EvaluateResult evaluated = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - - switch (evaluated.type()) { - case EvaluateResult::ResultType::kString: { - std::locale locale{"en_US.UTF-8"}; - std::string str = nanopb::MakeString(evaluated.value()->string_value); - std::transform(str.begin(), str.end(), str.begin(), - [&locale](char c) { return std::toupper(c, locale); }); - return EvaluateResult::NewValue(model::StringValue(str)); - } - case EvaluateResult::ResultType::kNull: - return EvaluateResult::NewNull(); - default: - return EvaluateResult::NewError(); // Type mismatch or Error/Unset - } -} - -EvaluateResult CoreTrim::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, "trim() requires exactly 1 param"); - EvaluateResult evaluated = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - - switch (evaluated.type()) { - case EvaluateResult::ResultType::kString: { - std::string str = nanopb::MakeString(evaluated.value()->string_value); - absl::string_view trimmed_view = absl::StripAsciiWhitespace(str); - return EvaluateResult::NewValue(model::StringValue(trimmed_view)); - } - case EvaluateResult::ResultType::kNull: - return EvaluateResult::NewNull(); - default: - return EvaluateResult::NewError(); // Type mismatch or Error/Unset - } -} - -EvaluateResult CoreStringReverse::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "reverse() requires exactly 1 param"); - EvaluateResult evaluated = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - - switch (evaluated.type()) { - case EvaluateResult::ResultType::kString: { - std::string reversed; - bool is_valid_utf8 = ProcessUtf8( - nanopb::MakeString(evaluated.value()->string_value), &reversed, - [](std::string* reversed_str, uint32_t /*code_point*/, - absl::string_view utf8_bytes) { - reversed_str->insert(0, utf8_bytes.data(), utf8_bytes.size()); - }); - - if (is_valid_utf8) { - return EvaluateResult::NewValue(model::StringValue(reversed)); - } - - return EvaluateResult::NewError(); - } - case EvaluateResult::ResultType::kNull: - return EvaluateResult::NewNull(); - default: - return EvaluateResult::NewError(); // Type mismatch or Error/Unset - } -} - -// --- Map Expression Implementations --- - -EvaluateResult CoreMapGet::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 2, - "map_get() function requires exactly 2 params (map and key)"); - - // Evaluate the map operand (param 0) - std::unique_ptr map_evaluable = - expr_->params()[0]->ToEvaluable(); - EvaluateResult map_result = map_evaluable->Evaluate(context, document); - - switch (map_result.type()) { - case EvaluateResult::ResultType::kUnset: { - // If the map itself is unset, the result is unset - return EvaluateResult::NewUnset(); - } - case EvaluateResult::ResultType::kMap: { - // Expected type, continue - break; - } - default: { - // Any other type (including Null, Error) is an error - return EvaluateResult::NewError(); - } - } - - // Evaluate the key operand (param 1) - std::unique_ptr key_evaluable = - expr_->params()[1]->ToEvaluable(); - EvaluateResult key_result = key_evaluable->Evaluate(context, document); - - absl::optional key_string; - switch (key_result.type()) { - case EvaluateResult::ResultType::kString: { - key_string = nanopb::MakeString(key_result.value()->string_value); - HARD_ASSERT(key_string.has_value(), "Failed to extract string key"); - break; - } - default: { - // Key must be a string, otherwise it's an error - return EvaluateResult::NewError(); - } - } - - // Look up the field in the map value - const auto* entry = model::FindEntry(*map_result.value(), key_string.value()); - - if (entry != nullptr) { - // Key found, return a deep clone of the value - return EvaluateResult::NewValue(model::DeepClone(entry->value)); - } else { - // Key not found, return Unset - return EvaluateResult::NewUnset(); - } -} - -// --- Arithmetic Implementations --- -EvaluateResult ArithmeticBase::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() >= 2, - "%s() function requires at least 2 params", expr_->name()); - - EvaluateResult current_result = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - - for (size_t i = 1; i < expr_->params().size(); ++i) { - // Check current accumulated result before evaluating next operand - if (current_result.IsErrorOrUnset()) { - // Propagate error immediately if accumulated result is error/unset - // Note: Unset is treated as Error in arithmetic according to TS logic - return EvaluateResult::NewError(); - } - // Null check happens inside ApplyOperation - - EvaluateResult next_operand = - expr_->params()[i]->ToEvaluable()->Evaluate(context, document); - - // Apply the operation - current_result = ApplyOperation(current_result, next_operand); - - // If ApplyOperation resulted in error or unset, propagate immediately as - // error - if (current_result.IsErrorOrUnset()) { - // Treat Unset from ApplyOperation as Error for propagation - return EvaluateResult::NewError(); - } - // Null is handled within the loop by ApplyOperation in the next iteration - } - - return current_result; -} - -inline EvaluateResult ArithmeticBase::ApplyOperation( - const EvaluateResult& left, const EvaluateResult& right) const { - // Mirroring TypeScript logic: - // 1. Check for Error/Unset first - if (left.IsErrorOrUnset() || right.IsErrorOrUnset()) { - return EvaluateResult::NewError(); - } - // 2. Check for Null - if (left.IsNull() || right.IsNull()) { - return EvaluateResult::NewNull(); - } - - // 3. Type check: Both must be numbers - const google_firestore_v1_Value* left_val = left.value(); - const google_firestore_v1_Value* right_val = right.value(); - if (!model::IsNumber(*left_val) || !model::IsNumber(*right_val)) { - return EvaluateResult::NewError(); // Type error - } - - // 4. Determine operation type (Integer or Double) - if (model::IsDouble(*left_val) || model::IsDouble(*right_val)) { - // Promote to double - double left_double_val = model::IsDouble(*left_val) - ? left_val->double_value - : static_cast(left_val->integer_value); - double right_double_val = - model::IsDouble(*right_val) - ? right_val->double_value - : static_cast(right_val->integer_value); - - // NaN propagation and specific error handling (like div/mod by zero) - // are handled within PerformDoubleOperation. - return PerformDoubleOperation(left_double_val, right_double_val); - - } else { - // Both are integers - absl::optional left_int_opt = model::GetInteger(*left_val); - absl::optional right_int_opt = model::GetInteger(*right_val); - // These should always succeed because we already checked IsNumber and - // excluded IsDouble. - HARD_ASSERT(left_int_opt.has_value() && right_int_opt.has_value(), - "Failed to extract integer values after IsNumber check"); - - return PerformIntegerOperation(left_int_opt.value(), right_int_opt.value()); - } -} - -EvaluateResult CoreAdd::PerformIntegerOperation(int64_t l, int64_t r) const { - auto const result = SafeAdd(l, r); - if (result.has_value()) { - return EvaluateResult::NewValue(IntValue(result.value())); - } - - return EvaluateResult::NewError(); -} - -EvaluateResult CoreAdd::PerformDoubleOperation(double l, double r) const { - return EvaluateResult::NewValue(DoubleValue(l + r)); -} - -EvaluateResult CoreSubtract::PerformIntegerOperation(int64_t l, - int64_t r) const { - auto const result = SafeSubtract(l, r); - if (result.has_value()) { - return EvaluateResult::NewValue(IntValue(result.value())); - } - - return EvaluateResult::NewError(); -} - -EvaluateResult CoreSubtract::PerformDoubleOperation(double l, double r) const { - return EvaluateResult::NewValue(DoubleValue(l - r)); -} - -EvaluateResult CoreMultiply::PerformIntegerOperation(int64_t l, - int64_t r) const { - auto const result = SafeMultiply(l, r); - if (result.has_value()) { - return EvaluateResult::NewValue(IntValue(result.value())); - } - - return EvaluateResult::NewError(); -} - -EvaluateResult CoreMultiply::PerformDoubleOperation(double l, double r) const { - return EvaluateResult::NewValue(DoubleValue(l * r)); -} - -EvaluateResult CoreDivide::PerformIntegerOperation(int64_t l, int64_t r) const { - auto const result = SafeDivide(l, r); - if (result.has_value()) { - return EvaluateResult::NewValue(IntValue(result.value())); - } - - return EvaluateResult::NewError(); -} - -EvaluateResult CoreDivide::PerformDoubleOperation(double l, double r) const { - // C++ double division handles signed zero correctly according to IEEE - // 754. +x / +0 -> +Inf -x / +0 -> -Inf +x / -0 -> -Inf -x / -0 -> +Inf - // 0 / 0 -> NaN - return EvaluateResult::NewValue(DoubleValue(l / r)); -} - -EvaluateResult CoreMod::PerformIntegerOperation(int64_t l, int64_t r) const { - auto const result = SafeMod(l, r); - if (result.has_value()) { - return EvaluateResult::NewValue(IntValue(result.value())); - } - - return EvaluateResult::NewError(); -} - -EvaluateResult CoreMod::PerformDoubleOperation(double l, double r) const { - if (r == 0.0) { - return EvaluateResult::NewValue( - DoubleValue(std::numeric_limits::quiet_NaN())); - } - // Use std::fmod for double modulo, matches C++ and Firestore semantics - return EvaluateResult::NewValue(DoubleValue(std::fmod(l, r))); -} - -// --- Array Expression Implementations --- - -EvaluateResult CoreArrayReverse::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "array_reverse() function requires exactly 1 param"); - - std::unique_ptr operand_evaluable = - expr_->params()[0]->ToEvaluable(); - EvaluateResult evaluated = operand_evaluable->Evaluate(context, document); - - switch (evaluated.type()) { - case EvaluateResult::ResultType::kNull: { - return EvaluateResult::NewNull(); - } - case EvaluateResult::ResultType::kArray: { - std::vector> reversed_values; - if (evaluated.value()->array_value.values != nullptr) { - for (pb_size_t i = 0; i < evaluated.value()->array_value.values_count; - ++i) { - // Deep clone each element to get a new FieldValue wrapper - reversed_values.push_back( - model::DeepClone(evaluated.value()->array_value.values[i])); - } - } - - std::reverse(reversed_values.begin(), reversed_values.end()); - return EvaluateResult::NewValue( - model::ArrayValue(std::move(reversed_values))); - } - default: - return EvaluateResult::NewError(); - } -} - -EvaluateResult CoreArrayContains::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 2, - "array_contains() function requires exactly 2 params"); - - std::vector> reversed_params( - expr_->params().rbegin(), expr_->params().rend()); - auto const equal_any = - CoreEqAny(api::FunctionExpr("equal_any", std::move(reversed_params))); - return equal_any.Evaluate(context, document); -} - -EvaluateResult CoreArrayContainsAll::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 2, - "array_contains_all() function requires exactly 2 params"); - - bool found_null = false; - - // Evaluate the array to search (param 0) - std::unique_ptr array_to_search_evaluable = - expr_->params()[0]->ToEvaluable(); - EvaluateResult array_to_search = - array_to_search_evaluable->Evaluate(context, document); - - switch (array_to_search.type()) { - case EvaluateResult::ResultType::kArray: { - break; // Expected type - } - case EvaluateResult::ResultType::kNull: { - found_null = true; - break; - } - default: { - return EvaluateResult::NewError(); // Error or Unset or wrong type - } - } - - // Evaluate the elements to find (param 1) - std::unique_ptr elements_to_find_evaluable = - expr_->params()[1]->ToEvaluable(); - EvaluateResult elements_to_find = - elements_to_find_evaluable->Evaluate(context, document); - - switch (elements_to_find.type()) { - case EvaluateResult::ResultType::kArray: { - break; // Expected type - } - case EvaluateResult::ResultType::kNull: { - found_null = true; - break; - } - default: { - // Handle all other types (kError, kUnset, kBoolean, kInt, kDouble, etc.) - // as errors for the 'elements_to_find' parameter. - return EvaluateResult::NewError(); - } - } - - // If either input was null, the result is null - if (found_null) { - return EvaluateResult::NewNull(); - } - - const google_firestore_v1_Value* search_values_proto = - elements_to_find.value(); - const google_firestore_v1_Value* array_values_proto = array_to_search.value(); - bool found_null_at_least_once = false; - - // Iterate through elements we need to find (search_values) - if (search_values_proto->array_value.values != nullptr) { - for (pb_size_t i = 0; i < search_values_proto->array_value.values_count; - ++i) { - const google_firestore_v1_Value& search = - search_values_proto->array_value.values[i]; - bool found = false; - - // Iterate through the array we are searching within (array_values) - if (array_values_proto->array_value.values != nullptr) { - for (pb_size_t j = 0; j < array_values_proto->array_value.values_count; - ++j) { - const google_firestore_v1_Value& value = - array_values_proto->array_value.values[j]; - - switch (model::StrictEquals(search, value)) { - case model::StrictEqualsResult::kEq: { - found = true; - break; // Found it, break inner loop - } - case model::StrictEqualsResult::kNotEq: { - // Keep searching - break; - } - case model::StrictEqualsResult::kNull: { - found_null = true; - found_null_at_least_once = true; // Track null globally - break; - } - } - if (found) { - break; // Exit inner loop once found - } - } // End inner loop (searching array_values) - } - - // Check result for the current 'search' element - if (found) { - // true case - do nothing, we found a match, make sure all other values - // are also found - } else { - // false case - we didn't find a match, short circuit - if (!found_null) { - return EvaluateResult::NewValue( - nanopb::MakeMessage(model::FalseValue())); - } - // null case - do nothing, we found at least one null value for this - // search element, keep going - } - } // End outer loop (iterating search_values) - } - - // If we finished the outer loop - if (found_null_at_least_once) { - // If we encountered any null comparison and didn't return false earlier, - // the result is null. - return EvaluateResult::NewNull(); - } else { - // If we finished and found no nulls, and never returned false, - // it means all elements were found. - return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); - } -} - -EvaluateResult CoreArrayContainsAny::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 2, - "array_contains_any() function requires exactly 2 params"); - - bool found_null = false; - - // Evaluate the array to search (param 0) - std::unique_ptr array_to_search_evaluable = - expr_->params()[0]->ToEvaluable(); - EvaluateResult array_to_search = - array_to_search_evaluable->Evaluate(context, document); - - switch (array_to_search.type()) { - case EvaluateResult::ResultType::kArray: { - break; // Expected type - } - case EvaluateResult::ResultType::kNull: { - found_null = true; - break; - } - default: { - return EvaluateResult::NewError(); // Error or Unset or wrong type - } - } - - // Evaluate the elements to find (param 1) - std::unique_ptr elements_to_find_evaluable = - expr_->params()[1]->ToEvaluable(); - EvaluateResult elements_to_find = - elements_to_find_evaluable->Evaluate(context, document); - - switch (elements_to_find.type()) { - case EvaluateResult::ResultType::kArray: { - break; // Expected type - } - case EvaluateResult::ResultType::kNull: { - found_null = true; - break; - } - default: { - // Handle all other types (kError, kUnset, kBoolean, kInt, kDouble, etc.) - // as errors for the 'elements_to_find' parameter. - return EvaluateResult::NewError(); - } - } - - // If either input was null, the result is null - if (found_null) { - return EvaluateResult::NewNull(); - } - - const google_firestore_v1_Value* search_values_proto = - elements_to_find.value(); - const google_firestore_v1_Value* array_values_proto = array_to_search.value(); - - // Outer loop: Iterate through the array being searched - if (search_values_proto->array_value.values != nullptr) { - for (pb_size_t i = 0; i < search_values_proto->array_value.values_count; - ++i) { - const google_firestore_v1_Value& candidate = - search_values_proto->array_value.values[i]; - - // Inner loop: Iterate through the elements to find - if (array_values_proto->array_value.values != nullptr) { - for (pb_size_t j = 0; j < array_values_proto->array_value.values_count; - ++j) { - const google_firestore_v1_Value& search_element = - array_values_proto->array_value.values[j]; - - switch (model::StrictEquals(candidate, search_element)) { - case model::StrictEqualsResult::kEq: { - // Found one match, return true immediately - return EvaluateResult::NewValue( - nanopb::MakeMessage(model::TrueValue())); - } - case model::StrictEqualsResult::kNotEq: - // Continue inner loop - break; - case model::StrictEqualsResult::kNull: - // Track null, continue inner loop - found_null = true; - break; - } - } // End inner loop - } - } // End outer loop - } - - // If we finished both loops without returning true - if (found_null) { - // If we encountered any null comparison, the result is null - return EvaluateResult::NewNull(); - } else { - // If no match was found and no nulls were encountered - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } -} - -EvaluateResult CoreArrayLength::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "array_length() function requires exactly 1 param"); - - std::unique_ptr operand_evaluable = - expr_->params()[0]->ToEvaluable(); - EvaluateResult operand_result = - operand_evaluable->Evaluate(context, document); - - switch (operand_result.type()) { - case EvaluateResult::ResultType::kNull: { - return EvaluateResult::NewNull(); - } - case EvaluateResult::ResultType::kArray: { - size_t array_size = operand_result.value()->array_value.values_count; - return EvaluateResult::NewValue(IntValue(array_size)); - } - default: { - return EvaluateResult::NewError(); - } - } -} - -// --- Logical Expression Implementations --- - -// Constructor definitions removed as they are now inline in the header - -EvaluateResult CoreAnd::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - bool has_null = false; - bool has_error = false; - for (const auto& param : expr_->params()) { - EvaluateResult const result = - param->ToEvaluable()->Evaluate(context, document); - switch (result.type()) { - case EvaluateResult::ResultType::kBoolean: - if (!result.value()->boolean_value) { - // Short-circuit on false - return EvaluateResult::NewValue( - nanopb::MakeMessage(model::FalseValue())); - } - break; // Break if true - case EvaluateResult::ResultType::kNull: - has_null = true; // Track null, continue evaluation - break; - default: - has_error = true; - break; - } - } - - if (has_error) { - return EvaluateResult::NewError(); // If any operand results in error - } - - if (has_null) { - return EvaluateResult::NewNull(); // If null was encountered, result is - // null - } - - return EvaluateResult::NewValue( - nanopb::MakeMessage(model::TrueValue())); // Otherwise, result is true -} - -EvaluateResult CoreOr::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - bool has_null = false; - bool has_error = false; - for (const auto& param : expr_->params()) { - EvaluateResult const result = - param->ToEvaluable()->Evaluate(context, document); - switch (result.type()) { - case EvaluateResult::ResultType::kBoolean: - if (result.value()->boolean_value) { - // Short-circuit on true - return EvaluateResult::NewValue( - nanopb::MakeMessage(model::TrueValue())); - } - break; // Continue if false - case EvaluateResult::ResultType::kNull: - has_null = true; // Track null, continue evaluation - break; - default: - has_error = true; - break; - } - } - - // If loop completes without returning true: - if (has_error) { - return EvaluateResult::NewError(); - } - - if (has_null) { - return EvaluateResult::NewNull(); - } - - return EvaluateResult::NewValue( - nanopb::MakeMessage(model::FalseValue())); // Otherwise, result is false -} - -EvaluateResult CoreXor::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - bool current_xor_result = false; - bool has_null = false; - for (const auto& param : expr_->params()) { - EvaluateResult const evaluated = - param->ToEvaluable()->Evaluate(context, document); - switch (evaluated.type()) { - case EvaluateResult::ResultType::kBoolean: { - bool operand_value = evaluated.value()->boolean_value; - // XOR logic: result = result ^ operand - current_xor_result = current_xor_result != operand_value; - break; - } - case EvaluateResult::ResultType::kNull: { - has_null = true; - break; - } - default: { - // Any non-boolean, non-null operand results in error - return EvaluateResult::NewError(); - } - } - } - - if (has_null) { - return EvaluateResult::NewNull(); - } - return EvaluateResult::NewValue(nanopb::MakeMessage( - current_xor_result ? model::TrueValue() : model::FalseValue())); -} - -EvaluateResult CoreCond::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 3, - "cond() function requires exactly 3 params"); - - EvaluateResult condition = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - - switch (condition.type()) { - case EvaluateResult::ResultType::kBoolean: { - if (condition.value()->boolean_value) { - // Condition is true, evaluate the second parameter - return expr_->params()[1]->ToEvaluable()->Evaluate(context, document); - } else { - // Condition is false, evaluate the third parameter - return expr_->params()[2]->ToEvaluable()->Evaluate(context, document); - } - } - case EvaluateResult::ResultType::kNull: { - // Condition is null, evaluate the third parameter (false case) - return expr_->params()[2]->ToEvaluable()->Evaluate(context, document); - } - default: - // Condition is error, unset, or non-boolean/non-null type - return EvaluateResult::NewError(); - } -} - -EvaluateResult CoreEqAny::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT( - expr_->params().size() == 2, - "equal_any() function requires exactly 2 params (search value and " - "array value)"); - - bool found_null = false; - - // Evaluate the search value (param 0) - EvaluateResult const search_result = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - switch (search_result.type()) { - case EvaluateResult::ResultType::kNull: { - found_null = true; - break; - } - case EvaluateResult::ResultType::kError: - case EvaluateResult::ResultType::kUnset: - return EvaluateResult::NewError(); // Error/Unset search value is error - default: - break; // Valid value - } - - EvaluateResult const array_result = - expr_->params()[1]->ToEvaluable()->Evaluate(context, document); - switch (array_result.type()) { - case EvaluateResult::ResultType::kNull: { - found_null = true; - break; - } - case EvaluateResult::ResultType::kArray: { - break; - } - default: - return EvaluateResult::NewError(); - } - - if (found_null) { - return EvaluateResult::NewNull(); - } - - for (size_t i = 0; i < array_result.value()->array_value.values_count; ++i) { - const google_firestore_v1_Value& candidate = - array_result.value()->array_value.values[i]; - switch (model::StrictEquals(*search_result.value(), candidate)) { - case model::StrictEqualsResult::kEq: { - return EvaluateResult::NewValue( - nanopb::MakeMessage(model::TrueValue())); - } - case model::StrictEqualsResult::kNotEq: { - break; - } - case model::StrictEqualsResult::kNull: { - found_null = true; - break; - } - } - } - - if (found_null) { - return EvaluateResult::NewNull(); - } - - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); -} - -EvaluateResult CoreNotEqAny::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT( - expr_->params().size() == 2, - "not_eq_any() function requires exactly 2 params (search value and " - "array value)"); - - CoreNot equivalent(api::FunctionExpr( - "not", - {std::make_shared("equal_any", expr_->params())})); - return equivalent.Evaluate(context, document); -} - -EvaluateResult CoreIsNan::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "is_nan() function requires exactly 1 param"); - - EvaluateResult evaluated = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - switch (evaluated.type()) { - case EvaluateResult::ResultType::kInt: - // Integers are never NaN - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - case EvaluateResult::ResultType::kDouble: - // Check if the double value is NaN - return EvaluateResult::NewValue(nanopb::MakeMessage( - model::IsNaNValue(*evaluated.value()) ? model::TrueValue() - : model::FalseValue())); - case EvaluateResult::ResultType::kNull: - // is_nan(null) -> null - return EvaluateResult::NewNull(); - default: - // is_nan applied to non-numeric, non-null is an error - return EvaluateResult::NewError(); - } -} - -EvaluateResult CoreIsNotNan::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "is_not_nan() function requires exactly 1 param"); - - CoreNot equivalent(api::FunctionExpr( - "not", {std::make_shared("is_nan", expr_->params())})); - return equivalent.Evaluate(context, document); -} - -EvaluateResult CoreIsNull::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "is_null() function requires exactly 1 param"); - - EvaluateResult evaluated = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - switch (evaluated.type()) { - case EvaluateResult::ResultType::kNull: - return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); - case EvaluateResult::ResultType::kUnset: - case EvaluateResult::ResultType::kError: - // is_null on error/unset is an error - return EvaluateResult::NewError(); - default: - // is_null on any other value is false - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } -} - -EvaluateResult CoreIsNotNull::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "is_not_null() function requires exactly 1 param"); - - CoreNot equivalent(api::FunctionExpr( - "not", - {std::make_shared("is_null", expr_->params())})); - return equivalent.Evaluate(context, document); -} - -EvaluateResult CoreIsError::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "is_error() function requires exactly 1 param"); - - EvaluateResult evaluated = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - switch (evaluated.type()) { - case EvaluateResult::ResultType::kError: - return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); - default: - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - } -} - -EvaluateResult CoreMaximum::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - // Store the underlying Value proto in the optional, not EvaluateResult - absl::optional> max_value_proto; - - for (const auto& param : expr_->params()) { - EvaluateResult result = param->ToEvaluable()->Evaluate(context, document); - - switch (result.type()) { - case EvaluateResult::ResultType::kError: - case EvaluateResult::ResultType::kUnset: - case EvaluateResult::ResultType::kNull: - // Skip null, error, unset - continue; - default: { - if (!max_value_proto.has_value() || - model::Compare(*result.value(), *max_value_proto.value()) == - util::ComparisonResult::Descending) { - // Store a deep copy of the value proto - max_value_proto = model::DeepClone(*result.value()); - } - } - } - } - - if (max_value_proto.has_value()) { - // Reconstruct EvaluateResult from the stored proto - return EvaluateResult::NewValue(std::move(max_value_proto.value())); - } - // If only null/error/unset were encountered, return Null - return EvaluateResult::NewNull(); -} - -EvaluateResult CoreMinimum::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - // Store the underlying Value proto in the optional, not EvaluateResult - absl::optional> min_value_proto; - - for (const auto& param : expr_->params()) { - EvaluateResult result = param->ToEvaluable()->Evaluate(context, document); - - switch (result.type()) { - case EvaluateResult::ResultType::kError: - case EvaluateResult::ResultType::kUnset: - case EvaluateResult::ResultType::kNull: - // Skip null, error, unset - continue; - default: { - if (!min_value_proto.has_value() || - model::Compare(*result.value(), *min_value_proto.value()) == - util::ComparisonResult::Ascending) { - min_value_proto = model::DeepClone(*result.value()); - } - } - } - } - - if (min_value_proto.has_value()) { - // Reconstruct EvaluateResult from the stored proto - return EvaluateResult::NewValue(std::move(min_value_proto.value())); - } - // If only null/error/unset were encountered, return Null - return EvaluateResult::NewNull(); -} - -// --- Debugging Expression Implementations --- - -EvaluateResult CoreExists::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "exists() function requires exactly 1 param"); - - std::unique_ptr operand_evaluable = - expr_->params()[0]->ToEvaluable(); - EvaluateResult evaluated = operand_evaluable->Evaluate(context, document); - - switch (evaluated.type()) { - case EvaluateResult::ResultType::kError: - return EvaluateResult::NewError(); // Propagate error - case EvaluateResult::ResultType::kUnset: - // Unset field means it doesn't exist - return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); - default: - // Null or any other value means it exists - return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); - } -} - -EvaluateResult CoreNot::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "not() function requires exactly 1 param"); - - std::unique_ptr operand_evaluable = - expr_->params()[0]->ToEvaluable(); - EvaluateResult evaluated = operand_evaluable->Evaluate(context, document); - - switch (evaluated.type()) { - case EvaluateResult::ResultType::kBoolean: { - // Negate the boolean value - bool original_value = evaluated.value()->boolean_value; - return EvaluateResult::NewValue(nanopb::MakeMessage( - original_value ? model::FalseValue() : model::TrueValue())); - } - case EvaluateResult::ResultType::kNull: { - // NOT(NULL) -> NULL - return EvaluateResult::NewNull(); - } - default: { - // NOT applied to non-boolean, non-null is an error - return EvaluateResult::NewError(); - } - } -} - -namespace { -// timestamp utilities - -// --- Timestamp Constants --- -// 0001-01-01T00:00:00Z -constexpr int64_t kTimestampMinSeconds = -62135596800LL; -// 9999-12-31T23:59:59Z (max seconds part) -constexpr int64_t kTimestampMaxSeconds = 253402300799LL; -// Max nanoseconds part -constexpr int32_t kTimestampMaxNanos = 999999999; - -constexpr int64_t kMillisecondsPerSecond = 1000LL; -constexpr int64_t kMicrosecondsPerSecond = 1000000LL; -constexpr int64_t kNanosecondsPerMicrosecond = 1000LL; -constexpr int64_t kNanosecondsPerMillisecond = 1000000LL; -constexpr int64_t kNanosecondsPerSecond = 1000000000LL; - -// 0001-01-01T00:00:00.000Z -constexpr int64_t kTimestampMinMilliseconds = - kTimestampMinSeconds * kMillisecondsPerSecond; -// 9999-12-31T23:59:59.999Z -constexpr int64_t kTimestampMaxMilliseconds = - kTimestampMaxSeconds * kMillisecondsPerSecond + 999LL; - -// 0001-01-01T00:00:00.000000Z -constexpr int64_t kTimestampMinMicroseconds = - kTimestampMinSeconds * kMicrosecondsPerSecond; -// 9999-12-31T23:59:59.999999Z -constexpr int64_t kTimestampMaxMicroseconds = - kTimestampMaxSeconds * kMicrosecondsPerSecond + 999999LL; - -// --- Timestamp Helper Functions --- - -bool IsMicrosInBounds(int64_t micros) { - return micros >= kTimestampMinMicroseconds && - micros <= kTimestampMaxMicroseconds; -} - -bool IsMillisInBounds(int64_t millis) { - return millis >= kTimestampMinMilliseconds && - millis <= kTimestampMaxMilliseconds; -} - -bool IsSecondsInBounds(int64_t seconds) { - return seconds >= kTimestampMinSeconds && seconds <= kTimestampMaxSeconds; -} - -// Checks if a google_protobuf_Timestamp is within the valid Firestore range. -bool IsTimestampInBounds(const google_protobuf_Timestamp& ts) { - if (ts.seconds < kTimestampMinSeconds || ts.seconds > kTimestampMaxSeconds) { - return false; - } - // Nanos must be non-negative and less than 1 second. - if (ts.nanos < 0 || ts.nanos >= kNanosecondsPerSecond) { - return false; - } - // Additional checks for min/max boundaries. - if (ts.seconds == kTimestampMinSeconds && ts.nanos != 0) { - return false; // Min timestamp must have 0 nanos. - } - if (ts.seconds == kTimestampMaxSeconds && ts.nanos > kTimestampMaxNanos) { - return false; // Max timestamp allows up to 999,999,999 nanos. - } - return true; -} - -// Converts a google_protobuf_Timestamp to total microseconds since epoch. -// Returns nullopt if the timestamp is out of bounds or calculation overflows. -absl::optional TimestampToMicros(const google_protobuf_Timestamp& ts) { - if (!IsTimestampInBounds(ts)) { - return absl::nullopt; - } - - absl::optional seconds_part_micros = - SafeMultiply(ts.seconds, kMicrosecondsPerSecond); - if (!seconds_part_micros.has_value()) { - return absl::nullopt; // Overflow multiplying seconds - } - - // Integer division truncates towards zero. - int64_t nanos_part_micros = ts.nanos / kNanosecondsPerMicrosecond; - - absl::optional total_micros = - SafeAdd(seconds_part_micros.value(), nanos_part_micros); - - // Final check to ensure the result is within the representable microsecond - // range. - if (!total_micros.has_value() || !IsMicrosInBounds(total_micros.value())) { - return absl::nullopt; - } - - return total_micros; -} - -// Enum for time units used in timestamp arithmetic. -enum class TimeUnit { - kMicrosecond, - kMillisecond, - kSecond, - kMinute, - kHour, - kDay -}; - -// Parses a string representation of a time unit into the TimeUnit enum. -absl::optional ParseTimeUnit(const std::string& unit_str) { - if (unit_str == "microsecond") return TimeUnit::kMicrosecond; - if (unit_str == "millisecond") return TimeUnit::kMillisecond; - if (unit_str == "second") return TimeUnit::kSecond; - if (unit_str == "minute") return TimeUnit::kMinute; - if (unit_str == "hour") return TimeUnit::kHour; - if (unit_str == "day") return TimeUnit::kDay; - return absl::nullopt; // Invalid unit string -} - -// Calculates the total microseconds for a given unit and amount. -// Returns nullopt on overflow. -absl::optional MicrosFromUnitAndAmount(TimeUnit unit, int64_t amount) { - switch (unit) { - case TimeUnit::kMicrosecond: - return amount; // No multiplication needed, no overflow possible here. - case TimeUnit::kMillisecond: - return SafeMultiply( - amount, kNanosecondsPerMillisecond / kNanosecondsPerMicrosecond); - case TimeUnit::kSecond: - return SafeMultiply(amount, kMicrosecondsPerSecond); - case TimeUnit::kMinute: - return SafeMultiply(amount, 60LL * kMicrosecondsPerSecond); - case TimeUnit::kHour: - return SafeMultiply(amount, 3600LL * kMicrosecondsPerSecond); - case TimeUnit::kDay: - return SafeMultiply(amount, 86400LL * kMicrosecondsPerSecond); - default: - // Should not happen if ParseTimeUnit is used correctly. - HARD_FAIL("Invalid TimeUnit enum value"); - return absl::nullopt; - } -} - -// Helper to create a google_protobuf_Timestamp from seconds and nanos. -// Assumes inputs are already validated to be within bounds. -google_protobuf_Timestamp CreateTimestampProto(int64_t seconds, int32_t nanos) { - google_protobuf_Timestamp ts; - // Use direct member assignment for protobuf fields - ts.seconds = seconds; - ts.nanos = nanos; - return ts; -} - -// Helper function to adjust timestamp for negative nanoseconds. -// Returns the adjusted {seconds, nanos} pair. Returns nullopt if adjusting -// seconds underflows. -absl::optional> AdjustTimestamp(int64_t seconds, - int32_t nanos) { - if (nanos < 0) { - absl::optional adjusted_seconds = SafeSubtract(seconds, 1); - if (!adjusted_seconds.has_value()) { - return absl::nullopt; // Underflow during adjustment - } - // Ensure nanos is within [-1e9 + 1, -1] before adding 1e9. - // The modulo operation should guarantee this range for negative results. - return std::make_pair(adjusted_seconds.value(), - nanos + kNanosecondsPerSecond); - } - // No adjustment needed, return original values. - return std::make_pair(seconds, nanos); -} - -} // anonymous namespace - -// --- Timestamp Expression Implementations --- - -EvaluateResult UnixToTimestampBase::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "%s() function requires exactly 1 param", expr_->name()); - - EvaluateResult evaluated = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - - switch (evaluated.type()) { - case EvaluateResult::ResultType::kInt: { - absl::optional value = model::GetInteger(*evaluated.value()); - HARD_ASSERT(value.has_value(), "Integer value extraction failed"); - return ToTimestamp(value.value()); - } - case EvaluateResult::ResultType::kNull: - return EvaluateResult::NewNull(); - default: - // Type error (not integer or null) - return EvaluateResult::NewError(); - } -} - -EvaluateResult TimestampToUnixBase::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT(expr_->params().size() == 1, - "%s() function requires exactly 1 param", expr_->name()); - - EvaluateResult evaluated = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - - switch (evaluated.type()) { - case EvaluateResult::ResultType::kTimestamp: { - // Check if the input timestamp is within valid bounds before conversion. - if (!IsTimestampInBounds(evaluated.value()->timestamp_value)) { - return EvaluateResult::NewError(); - } - return ToUnix(evaluated.value()->timestamp_value); - } - case EvaluateResult::ResultType::kNull: - return EvaluateResult::NewNull(); - default: - // Type error (not timestamp or null) - return EvaluateResult::NewError(); - } -} - -EvaluateResult TimestampArithmeticBase::Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const { - HARD_ASSERT( - expr_->params().size() == 3, - "%s() function requires exactly 3 params (timestamp, unit, amount)", - expr_->name()); - - bool has_null = false; - - // 1. Evaluate Timestamp operand - EvaluateResult timestamp_result = - expr_->params()[0]->ToEvaluable()->Evaluate(context, document); - switch (timestamp_result.type()) { - case EvaluateResult::ResultType::kTimestamp: - // Check initial timestamp bounds - if (!IsTimestampInBounds(timestamp_result.value()->timestamp_value)) { - return EvaluateResult::NewError(); - } - break; - case EvaluateResult::ResultType::kNull: - has_null = true; - break; - default: - return EvaluateResult::NewError(); // Type error - } - - // 2. Evaluate Unit operand (must be string) - EvaluateResult unit_result = - expr_->params()[1]->ToEvaluable()->Evaluate(context, document); - absl::optional time_unit; - switch (unit_result.type()) { - case EvaluateResult::ResultType::kString: { - std::string unit_str = - nanopb::MakeString(unit_result.value()->string_value); - time_unit = ParseTimeUnit(unit_str); - if (!time_unit.has_value()) { - return EvaluateResult::NewError(); // Invalid unit string - } - break; - } - case EvaluateResult::ResultType::kNull: - has_null = true; - break; - default: - return EvaluateResult::NewError(); // Type error - } - - // 3. Evaluate Amount operand (must be integer) - EvaluateResult amount_result = - expr_->params()[2]->ToEvaluable()->Evaluate(context, document); - absl::optional amount; - switch (amount_result.type()) { - case EvaluateResult::ResultType::kInt: - amount = model::GetInteger(*amount_result.value()); - HARD_ASSERT(amount.has_value(), "Integer value extraction failed"); - break; - case EvaluateResult::ResultType::kNull: - has_null = true; - break; - default: - return EvaluateResult::NewError(); // Type error - } - - // Null propagation - if (has_null) { - return EvaluateResult::NewNull(); - } - - // Calculate initial micros and micros to operate - absl::optional initial_micros = - TimestampToMicros(timestamp_result.value()->timestamp_value); - if (!initial_micros.has_value()) { - // Should have been caught by IsTimestampInBounds earlier, but double-check. - return EvaluateResult::NewError(); - } - - absl::optional micros_to_operate = - MicrosFromUnitAndAmount(time_unit.value(), amount.value()); - if (!micros_to_operate.has_value()) { - return EvaluateResult::NewError(); // Overflow calculating micros delta - } - - // Perform the specific arithmetic (add or subtract) - absl::optional new_micros_opt = - PerformArithmetic(initial_micros.value(), micros_to_operate.value()); - if (!new_micros_opt.has_value()) { - return EvaluateResult::NewError(); // Arithmetic overflow/error - } - int64_t new_micros = new_micros_opt.value(); - - // Check final microsecond bounds - if (!IsMicrosInBounds(new_micros)) { - return EvaluateResult::NewError(); - } - - // Convert back to seconds and nanos - // Use SafeDivide to handle potential INT64_MIN / -1 edge case, though - // unlikely here. - absl::optional new_seconds_opt = - SafeDivide(new_micros, kMicrosecondsPerSecond); - if (!new_seconds_opt.has_value()) { - return EvaluateResult::NewError(); // Should not happen if IsMicrosInBounds - // passed - } - int64_t new_seconds = new_seconds_opt.value(); - int64_t nanos_remainder_micros = new_micros % kMicrosecondsPerSecond; - - // Adjust seconds and calculate nanos based on remainder sign - int32_t new_nanos; - if (nanos_remainder_micros < 0) { - // If remainder is negative, adjust seconds down and make nanos positive. - absl::optional adjusted_seconds_opt = SafeSubtract(new_seconds, 1); - if (!adjusted_seconds_opt.has_value()) - return EvaluateResult::NewError(); // Overflow - new_seconds = adjusted_seconds_opt.value(); - new_nanos = - static_cast((nanos_remainder_micros + kMicrosecondsPerSecond) * - kNanosecondsPerMicrosecond); - } else { - new_nanos = static_cast(nanos_remainder_micros * - kNanosecondsPerMicrosecond); - } - - // Create the final timestamp proto - google_protobuf_Timestamp result_ts = - CreateTimestampProto(new_seconds, new_nanos); - - // Final check on calculated timestamp bounds - if (!IsTimestampInBounds(result_ts)) { - return EvaluateResult::NewError(); - } - - // Wrap in Value proto and return - google_firestore_v1_Value result_value; - result_value.which_value_type = google_firestore_v1_Value_timestamp_value_tag; - result_value.timestamp_value = result_ts; // Copy the timestamp proto - return EvaluateResult::NewValue(nanopb::MakeMessage(std::move(result_value))); -} - -// --- Specific Timestamp Function Implementations --- - -// Define constructors declared in the header -CoreUnixMicrosToTimestamp::CoreUnixMicrosToTimestamp( - const api::FunctionExpr& expr) - : UnixToTimestampBase(expr) { -} -CoreUnixMillisToTimestamp::CoreUnixMillisToTimestamp( - const api::FunctionExpr& expr) - : UnixToTimestampBase(expr) { -} -CoreUnixSecondsToTimestamp::CoreUnixSecondsToTimestamp( - const api::FunctionExpr& expr) - : UnixToTimestampBase(expr) { -} -CoreTimestampToUnixMicros::CoreTimestampToUnixMicros( - const api::FunctionExpr& expr) - : TimestampToUnixBase(expr) { -} -CoreTimestampToUnixMillis::CoreTimestampToUnixMillis( - const api::FunctionExpr& expr) - : TimestampToUnixBase(expr) { -} -CoreTimestampToUnixSeconds::CoreTimestampToUnixSeconds( - const api::FunctionExpr& expr) - : TimestampToUnixBase(expr) { -} -CoreTimestampAdd::CoreTimestampAdd(const api::FunctionExpr& expr) - : TimestampArithmeticBase(expr) { -} -CoreTimestampSub::CoreTimestampSub(const api::FunctionExpr& expr) - : TimestampArithmeticBase(expr) { -} - -// Define member function implementations -EvaluateResult CoreUnixMicrosToTimestamp::ToTimestamp(int64_t micros) const { - if (!IsMicrosInBounds(micros)) { - return EvaluateResult::NewError(); - } - - // Use SafeDivide to handle potential INT64_MIN / -1 edge case, though - // unlikely here. - absl::optional seconds_opt = - SafeDivide(micros, kMicrosecondsPerSecond); - if (!seconds_opt.has_value()) return EvaluateResult::NewError(); - int64_t initial_seconds = seconds_opt.value(); - // Calculate initial nanos directly from the remainder. - int32_t initial_nanos = static_cast( - (micros % kMicrosecondsPerSecond) * kNanosecondsPerMicrosecond); - - // Adjust for negative nanoseconds using the helper function. - absl::optional> adjusted_ts = - AdjustTimestamp(initial_seconds, initial_nanos); - - if (!adjusted_ts.has_value()) { - return EvaluateResult::NewError(); // Overflow during adjustment - } - - int64_t final_seconds = adjusted_ts.value().first; - int32_t final_nanos = adjusted_ts.value().second; - - google_firestore_v1_Value result_value; - result_value.which_value_type = google_firestore_v1_Value_timestamp_value_tag; - result_value.timestamp_value = - CreateTimestampProto(final_seconds, final_nanos); - - // Final bounds check after adjustment. - if (!IsTimestampInBounds(result_value.timestamp_value)) { - return EvaluateResult::NewError(); - } - - return EvaluateResult::NewValue(nanopb::MakeMessage(std::move(result_value))); -} - -EvaluateResult CoreUnixMillisToTimestamp::ToTimestamp(int64_t millis) const { - if (!IsMillisInBounds(millis)) { - return EvaluateResult::NewError(); - } - - absl::optional seconds_opt = - SafeDivide(millis, kMillisecondsPerSecond); - if (!seconds_opt.has_value()) return EvaluateResult::NewError(); - int64_t initial_seconds = seconds_opt.value(); - // Calculate initial nanos directly from the remainder. - int32_t initial_nanos = static_cast( - (millis % kMillisecondsPerSecond) * kNanosecondsPerMillisecond); - - // Adjust for negative nanoseconds using the helper function. - absl::optional> adjusted_ts = - AdjustTimestamp(initial_seconds, initial_nanos); - - if (!adjusted_ts.has_value()) { - return EvaluateResult::NewError(); // Overflow during adjustment - } - - int64_t final_seconds = adjusted_ts.value().first; - int32_t final_nanos = adjusted_ts.value().second; - - google_firestore_v1_Value result_value; - result_value.which_value_type = google_firestore_v1_Value_timestamp_value_tag; - result_value.timestamp_value = - CreateTimestampProto(final_seconds, final_nanos); - - // Final bounds check after adjustment. - if (!IsTimestampInBounds(result_value.timestamp_value)) { - return EvaluateResult::NewError(); - } - - return EvaluateResult::NewValue(nanopb::MakeMessage(std::move(result_value))); -} - -EvaluateResult CoreUnixSecondsToTimestamp::ToTimestamp(int64_t seconds) const { - if (!IsSecondsInBounds(seconds)) { - return EvaluateResult::NewError(); - } - - google_firestore_v1_Value result_value; - result_value.which_value_type = google_firestore_v1_Value_timestamp_value_tag; - result_value.timestamp_value = - CreateTimestampProto(seconds, 0); // Nanos are always 0 - - // Bounds check is implicitly handled by IsSecondsInBounds - return EvaluateResult::NewValue(nanopb::MakeMessage(std::move(result_value))); -} - -EvaluateResult CoreTimestampToUnixMicros::ToUnix( - const google_protobuf_Timestamp& ts) const { - absl::optional micros = TimestampToMicros(ts); - // Check if the resulting micros are within representable bounds (already done - // in TimestampToMicros) - if (!micros.has_value()) { - return EvaluateResult::NewError(); - } - return EvaluateResult::NewValue(IntValue(micros.value())); -} - -EvaluateResult CoreTimestampToUnixMillis::ToUnix( - const google_protobuf_Timestamp& ts) const { - absl::optional micros_opt = TimestampToMicros(ts); - if (!micros_opt.has_value()) { - return EvaluateResult::NewError(); - } - int64_t micros = micros_opt.value(); - - // Perform division, truncating towards zero. - absl::optional millis_opt = SafeDivide(micros, 1000LL); - if (!millis_opt.has_value()) { - // This should ideally not happen if micros were in bounds, but check - // anyway. - return EvaluateResult::NewError(); - } - int64_t millis = millis_opt.value(); - - // Adjust for negative timestamps where truncation differs from floor - // division. If micros is negative and not perfectly divisible by 1000, - // subtract 1 from millis. - if (micros < 0 && (micros % 1000LL != 0)) { - absl::optional adjusted_millis_opt = SafeSubtract(millis, 1); - if (!adjusted_millis_opt.has_value()) - return EvaluateResult::NewError(); // Overflow check - millis = adjusted_millis_opt.value(); - } - - // Check if the resulting millis are within representable bounds - if (!IsMillisInBounds(millis)) { - return EvaluateResult::NewError(); - } - - return EvaluateResult::NewValue(IntValue(millis)); -} - -EvaluateResult CoreTimestampToUnixSeconds::ToUnix( - const google_protobuf_Timestamp& ts) const { - // Seconds are directly available and already checked by IsTimestampInBounds - // in base class. - int64_t seconds = ts.seconds; - // Check if the resulting seconds are within representable bounds (redundant - // but safe) - if (!IsSecondsInBounds(seconds)) { - return EvaluateResult::NewError(); - } - return EvaluateResult::NewValue(IntValue(seconds)); -} - -absl::optional CoreTimestampAdd::PerformArithmetic( - int64_t initial_micros, int64_t micros_to_operate) const { - return SafeAdd(initial_micros, micros_to_operate); -} - -absl::optional CoreTimestampSub::PerformArithmetic( - int64_t initial_micros, int64_t micros_to_operate) const { - return SafeSubtract(initial_micros, micros_to_operate); -} - -} // namespace core -} // namespace firestore -} // namespace firebase diff --git a/Firestore/core/src/core/expressions_eval.h b/Firestore/core/src/core/expressions_eval.h index 298d3e8b617..fbf2c197c7d 100644 --- a/Firestore/core/src/core/expressions_eval.h +++ b/Firestore/core/src/core/expressions_eval.h @@ -17,903 +17,15 @@ #ifndef FIRESTORE_CORE_SRC_CORE_EXPRESSIONS_EVAL_H_ #define FIRESTORE_CORE_SRC_CORE_EXPRESSIONS_EVAL_H_ -#include -#include -#include -#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" - -#include "Firestore/core/src/api/expressions.h" -#include "Firestore/core/src/api/stages.h" -#include "Firestore/core/src/nanopb/message.h" -#include "absl/types/optional.h" - -namespace firebase { -namespace firestore { -namespace core { - -// Forward declaration removed, definition moved below - -/** Represents the result of evaluating an expression. */ -class EvaluateResult { - public: - // TODO(BSON): Add bson types here when integrating. - enum class ResultType { - kError = 0, - kUnset = 1, - kNull = 2, - kBoolean = 3, - kInt = 4, - kDouble = 5, - kTimestamp = 6, - kString = 7, - kBytes = 8, - kReference = 9, - kGeoPoint = 10, - kArray = 11, - kMap = 12, - kFieldReference = 13, - kVector = 14 - }; - - // Disallow default instance as it is invalid - EvaluateResult() = delete; - - static EvaluateResult NewError() { - return EvaluateResult(ResultType::kError, - nanopb::Message()); - } - - static EvaluateResult NewUnset() { - return EvaluateResult(ResultType::kUnset, - nanopb::Message()); - } - - static EvaluateResult NewNull(); - - static EvaluateResult NewValue( - nanopb::Message value); - - ResultType type() const { - return type_; - } - - const google_firestore_v1_Value* value() const { - return value_.get(); - } - - bool IsErrorOrUnset() const { - return type_ == ResultType::kError || type_ == ResultType::kUnset; - } - - bool IsNull() const { - return type_ == ResultType::kNull; - } - - private: - EvaluateResult(ResultType type, - nanopb::Message message); - - nanopb::Message value_; - ResultType type_; -}; - -/** An interface representing an expression that can be evaluated. */ -class EvaluableExpr { - public: - virtual ~EvaluableExpr() = default; - - /** - * Evaluates the expression against the given document within the provided - * context. - * @param context The context for evaluation (e.g., variable bindings). - * @param document The document to evaluate against. - * @return The result of the evaluation. - */ - virtual EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const = 0; -}; - -class CoreField : public EvaluableExpr { - public: - explicit CoreField(std::unique_ptr expr) : expr_(std::move(expr)) { - } - - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreConstant : public EvaluableExpr { - public: - explicit CoreConstant(std::unique_ptr expr) - : expr_(std::move(expr)) { - } - - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -/** Base class for binary comparison expressions (==, !=, <, <=, >, >=). */ -class ComparisonBase : public EvaluableExpr { - public: - explicit ComparisonBase(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - protected: - /** - * Performs the specific comparison logic after operands have been evaluated - * and basic checks (Error, Unset, Null) have passed. - */ - virtual EvaluateResult CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const = 0; - - std::unique_ptr expr_; -}; - -class CoreEqual : public ComparisonBase { - public: - explicit CoreEqual(const api::FunctionExpr& expr) : ComparisonBase(expr) { - } - - protected: - EvaluateResult CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const override; -}; - -class CoreNotEqual : public ComparisonBase { - public: - explicit CoreNotEqual(const api::FunctionExpr& expr) : ComparisonBase(expr) { - } - - protected: - EvaluateResult CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const override; -}; - -class CoreLessThan : public ComparisonBase { - public: - explicit CoreLessThan(const api::FunctionExpr& expr) : ComparisonBase(expr) { - } - - protected: - EvaluateResult CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const override; -}; - -class CoreLessThanOrEqual : public ComparisonBase { - public: - explicit CoreLessThanOrEqual(const api::FunctionExpr& expr) - : ComparisonBase(expr) { - } - - protected: - EvaluateResult CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const override; -}; - -class CoreGreaterThan : public ComparisonBase { - public: - explicit CoreGreaterThan(const api::FunctionExpr& expr) - : ComparisonBase(expr) { - } - - protected: - EvaluateResult CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const override; -}; - -class CoreGreaterThanOrEqual : public ComparisonBase { - public: - explicit CoreGreaterThanOrEqual(const api::FunctionExpr& expr) - : ComparisonBase(expr) { - } - - protected: - EvaluateResult CompareToResult(const EvaluateResult& left, - const EvaluateResult& right) const override; -}; - -// --- Base Class for Arithmetic Operations --- -class ArithmeticBase : public EvaluableExpr { - public: - explicit ArithmeticBase(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - ~ArithmeticBase() override = default; - - // Implementation is inline below - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - protected: - // Performs the specific integer operation (e.g., add, subtract). - // Returns Error result on overflow or invalid operation (like div/mod by - // zero). - virtual EvaluateResult PerformIntegerOperation(int64_t lhs, - int64_t rhs) const = 0; - - // Performs the specific double operation. - // Returns Error result on invalid operation (like div/mod by zero). - virtual EvaluateResult PerformDoubleOperation(double lhs, - double rhs) const = 0; - - // Applies the arithmetic operation between two evaluated results. - // Mirrors the logic from TypeScript's applyArithmetics. - // Implementation is inline below - EvaluateResult ApplyOperation(const EvaluateResult& left, - const EvaluateResult& right) const; - - std::unique_ptr expr_; -}; -// --- End Base Class for Arithmetic Operations --- - -class CoreAdd : public ArithmeticBase { - public: - explicit CoreAdd(const api::FunctionExpr& expr) : ArithmeticBase(expr) { - } - - protected: - EvaluateResult PerformIntegerOperation(int64_t lhs, - int64_t rhs) const override; - EvaluateResult PerformDoubleOperation(double lhs, double rhs) const override; -}; - -class CoreSubtract : public ArithmeticBase { - public: - explicit CoreSubtract(const api::FunctionExpr& expr) : ArithmeticBase(expr) { - } - - protected: - EvaluateResult PerformIntegerOperation(int64_t lhs, - int64_t rhs) const override; - EvaluateResult PerformDoubleOperation(double lhs, double rhs) const override; -}; - -class CoreMultiply : public ArithmeticBase { - public: - explicit CoreMultiply(const api::FunctionExpr& expr) : ArithmeticBase(expr) { - } - - protected: - EvaluateResult PerformIntegerOperation(int64_t lhs, - int64_t rhs) const override; - EvaluateResult PerformDoubleOperation(double lhs, double rhs) const override; -}; - -class CoreDivide : public ArithmeticBase { - public: - explicit CoreDivide(const api::FunctionExpr& expr) : ArithmeticBase(expr) { - } - - protected: - EvaluateResult PerformIntegerOperation(int64_t lhs, - int64_t rhs) const override; - EvaluateResult PerformDoubleOperation(double lhs, double rhs) const override; -}; - -class CoreMod : public ArithmeticBase { - public: - explicit CoreMod(const api::FunctionExpr& expr) : ArithmeticBase(expr) { - } - - protected: - EvaluateResult PerformIntegerOperation(int64_t lhs, - int64_t rhs) const override; - EvaluateResult PerformDoubleOperation(double lhs, double rhs) const override; -}; - -// --- Array Expressions --- - -class CoreArrayReverse : public EvaluableExpr { - public: - explicit CoreArrayReverse(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreArrayContains : public EvaluableExpr { - public: - explicit CoreArrayContains(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreArrayContainsAll : public EvaluableExpr { - public: - explicit CoreArrayContainsAll(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreArrayContainsAny : public EvaluableExpr { - public: - explicit CoreArrayContainsAny(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreArrayLength : public EvaluableExpr { - public: - explicit CoreArrayLength(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -// --- String Expressions --- - -/** Base class for binary string search functions (starts_with, ends_with, - * str_contains). */ -class StringSearchBase : public EvaluableExpr { - public: - explicit StringSearchBase(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - protected: - /** - * Performs the specific string search logic after operands have been - * evaluated and basic checks (Error, Unset, Null, Type) have passed. - */ - virtual EvaluateResult PerformSearch(const std::string& value, - const std::string& search) const = 0; - - std::unique_ptr expr_; -}; - -class CoreByteLength : public EvaluableExpr { - public: - explicit CoreByteLength(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreCharLength : public EvaluableExpr { - public: - explicit CoreCharLength(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreStringConcat : public EvaluableExpr { - public: - explicit CoreStringConcat(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreEndsWith : public StringSearchBase { - public: - explicit CoreEndsWith(const api::FunctionExpr& expr) - : StringSearchBase(expr) { - } - - protected: - EvaluateResult PerformSearch(const std::string& value, - const std::string& search) const override; -}; - -class CoreStartsWith : public StringSearchBase { - public: - explicit CoreStartsWith(const api::FunctionExpr& expr) - : StringSearchBase(expr) { - } - - protected: - EvaluateResult PerformSearch(const std::string& value, - const std::string& search) const override; -}; - -class CoreStringContains : public StringSearchBase { - public: - explicit CoreStringContains(const api::FunctionExpr& expr) - : StringSearchBase(expr) { - } - - protected: - EvaluateResult PerformSearch(const std::string& value, - const std::string& search) const override; -}; - -class CoreToLower : public EvaluableExpr { - public: - explicit CoreToLower(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreToUpper : public EvaluableExpr { - public: - explicit CoreToUpper(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreTrim : public EvaluableExpr { - public: - explicit CoreTrim(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreStringReverse : public EvaluableExpr { - public: - explicit CoreStringReverse(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreRegexContains : public StringSearchBase { - public: - explicit CoreRegexContains(const api::FunctionExpr& expr) - : StringSearchBase(expr) { - } - - protected: - EvaluateResult PerformSearch(const std::string& value, - const std::string& search) const override; -}; - -class CoreRegexMatch : public StringSearchBase { - public: - explicit CoreRegexMatch(const api::FunctionExpr& expr) - : StringSearchBase(expr) { - } - - protected: - EvaluateResult PerformSearch(const std::string& value, - const std::string& search) const override; -}; - -class CoreLike : public StringSearchBase { - public: - explicit CoreLike(const api::FunctionExpr& expr) : StringSearchBase(expr) { - } - - protected: - EvaluateResult PerformSearch(const std::string& value, - const std::string& search) const override; -}; - -// --- Map Expressions --- - -class CoreMapGet : public EvaluableExpr { - public: - explicit CoreMapGet(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -// --- Logical Expressions --- - -class CoreAnd : public EvaluableExpr { - public: - explicit CoreAnd(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreOr : public EvaluableExpr { - public: - explicit CoreOr(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreXor : public EvaluableExpr { - public: - explicit CoreXor(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreCond : public EvaluableExpr { - public: - explicit CoreCond(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreEqAny : public EvaluableExpr { - public: - explicit CoreEqAny(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreNotEqAny : public EvaluableExpr { - public: - explicit CoreNotEqAny(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreIsNan : public EvaluableExpr { - public: - explicit CoreIsNan(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreIsNotNan : public EvaluableExpr { - public: - explicit CoreIsNotNan(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreIsNull : public EvaluableExpr { - public: - explicit CoreIsNull(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreIsNotNull : public EvaluableExpr { - public: - explicit CoreIsNotNull(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreIsError : public EvaluableExpr { - public: - explicit CoreIsError(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreMaximum : public EvaluableExpr { - public: - explicit CoreMaximum(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreMinimum : public EvaluableExpr { - public: - explicit CoreMinimum(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -// --- Debugging Expressions --- - -class CoreExists : public EvaluableExpr { - public: - explicit CoreExists(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -class CoreNot : public EvaluableExpr { - public: - explicit CoreNot(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - private: - std::unique_ptr expr_; -}; - -// --- Timestamp Expressions --- - -/** Base class for converting Unix time (micros/millis/seconds) to Timestamp. */ -class UnixToTimestampBase : public EvaluableExpr { - public: - explicit UnixToTimestampBase(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - protected: - /** Performs the specific conversion logic after input validation. */ - virtual EvaluateResult ToTimestamp(int64_t value) const = 0; - - std::unique_ptr expr_; -}; - -// Note: Implementations are in expressions_eval.cc -class CoreUnixMicrosToTimestamp : public UnixToTimestampBase { - public: - explicit CoreUnixMicrosToTimestamp(const api::FunctionExpr& expr); - - protected: - EvaluateResult ToTimestamp(int64_t value) const override; -}; - -class CoreUnixMillisToTimestamp : public UnixToTimestampBase { - public: - explicit CoreUnixMillisToTimestamp(const api::FunctionExpr& expr); - - protected: - EvaluateResult ToTimestamp(int64_t value) const override; -}; - -class CoreUnixSecondsToTimestamp : public UnixToTimestampBase { - public: - explicit CoreUnixSecondsToTimestamp(const api::FunctionExpr& expr); - - protected: - EvaluateResult ToTimestamp(int64_t value) const override; -}; - -/** Base class for converting Timestamp to Unix time (micros/millis/seconds). */ -class TimestampToUnixBase : public EvaluableExpr { - public: - explicit TimestampToUnixBase(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - protected: - /** Performs the specific conversion logic after input validation. */ - virtual EvaluateResult ToUnix( - const google_protobuf_Timestamp& ts) const = 0; // Use protobuf type - - std::unique_ptr expr_; -}; - -// Note: Implementations are in expressions_eval.cc -class CoreTimestampToUnixMicros : public TimestampToUnixBase { - public: - explicit CoreTimestampToUnixMicros(const api::FunctionExpr& expr); - - protected: - EvaluateResult ToUnix(const google_protobuf_Timestamp& ts) const override; -}; - -class CoreTimestampToUnixMillis : public TimestampToUnixBase { - public: - explicit CoreTimestampToUnixMillis(const api::FunctionExpr& expr); - - protected: - EvaluateResult ToUnix(const google_protobuf_Timestamp& ts) const override; -}; - -class CoreTimestampToUnixSeconds : public TimestampToUnixBase { - public: - explicit CoreTimestampToUnixSeconds(const api::FunctionExpr& expr); - - protected: - EvaluateResult ToUnix(const google_protobuf_Timestamp& ts) const override; -}; - -/** Base class for timestamp arithmetic (add/sub). */ -class TimestampArithmeticBase : public EvaluableExpr { - public: - explicit TimestampArithmeticBase(const api::FunctionExpr& expr) - : expr_(std::make_unique(expr)) { - } - - EvaluateResult Evaluate( - const api::EvaluateContext& context, - const model::PipelineInputOutput& document) const override; - - protected: - /** Performs the specific arithmetic operation. */ - // Return optional as int128 is not needed and adds complexity - virtual absl::optional PerformArithmetic( - int64_t initial_micros, int64_t micros_to_operate) const = 0; - - std::unique_ptr expr_; -}; - -// Note: Implementations are in expressions_eval.cc -class CoreTimestampAdd : public TimestampArithmeticBase { - public: - explicit CoreTimestampAdd(const api::FunctionExpr& expr); - - protected: - absl::optional PerformArithmetic( - int64_t initial_micros, int64_t micros_to_operate) const override; -}; - -class CoreTimestampSub : public TimestampArithmeticBase { - public: - explicit CoreTimestampSub(const api::FunctionExpr& expr); - - protected: - absl::optional PerformArithmetic( - int64_t initial_micros, int64_t micros_to_operate) const override; -}; - -/** - * Converts a high-level expression representation into an evaluable one. - */ -std::unique_ptr FunctionToEvaluable( - const api::FunctionExpr& function); - -} // namespace core -} // namespace firestore -} // namespace firebase +#include "Firestore/core/src/core/pipeline/aggregates.h" +#include "Firestore/core/src/core/pipeline/evaluation/arithmetic.h" +#include "Firestore/core/src/core/pipeline/evaluation/array.h" +#include "Firestore/core/src/core/pipeline/evaluation/comparison.h" +#include "Firestore/core/src/core/pipeline/evaluation/logical.h" +#include "Firestore/core/src/core/pipeline/evaluation/map.h" +#include "Firestore/core/src/core/pipeline/evaluation/string.h" +#include "Firestore/core/src/core/pipeline/evaluation/timestamp.h" +#include "Firestore/core/src/core/pipeline/evaluation/type.h" +#include "Firestore/core/src/core/pipeline/expression.h" #endif // FIRESTORE_CORE_SRC_CORE_EXPRESSIONS_EVAL_H_ diff --git a/Firestore/core/src/core/pipeline/aggregates.cc b/Firestore/core/src/core/pipeline/aggregates.cc new file mode 100644 index 00000000000..176763fd4ef --- /dev/null +++ b/Firestore/core/src/core/pipeline/aggregates.cc @@ -0,0 +1,96 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/core/pipeline/aggregates.h" + +#include + +#include "Firestore/core/src/model/value_util.h" + +namespace firebase { +namespace firestore { +namespace core { + +EvaluateResult CoreMaximum::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + // Store the underlying Value proto in the optional, not EvaluateResult + absl::optional> max_value_proto; + + for (const auto& param : expr_->params()) { + EvaluateResult result = param->ToEvaluable()->Evaluate(context, document); + + switch (result.type()) { + case EvaluateResult::ResultType::kError: + case EvaluateResult::ResultType::kUnset: + case EvaluateResult::ResultType::kNull: + // Skip null, error, unset + continue; + default: { + if (!max_value_proto.has_value() || + model::Compare(*result.value(), *max_value_proto.value()) == + util::ComparisonResult::Descending) { + // Store a deep copy of the value proto + max_value_proto = model::DeepClone(*result.value()); + } + } + } + } + + if (max_value_proto.has_value()) { + // Reconstruct EvaluateResult from the stored proto + return EvaluateResult::NewValue(std::move(max_value_proto.value())); + } + // If only null/error/unset were encountered, return Null + return EvaluateResult::NewNull(); +} + +EvaluateResult CoreMinimum::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + // Store the underlying Value proto in the optional, not EvaluateResult + absl::optional> min_value_proto; + + for (const auto& param : expr_->params()) { + EvaluateResult result = param->ToEvaluable()->Evaluate(context, document); + + switch (result.type()) { + case EvaluateResult::ResultType::kError: + case EvaluateResult::ResultType::kUnset: + case EvaluateResult::ResultType::kNull: + // Skip null, error, unset + continue; + default: { + if (!min_value_proto.has_value() || + model::Compare(*result.value(), *min_value_proto.value()) == + util::ComparisonResult::Ascending) { + min_value_proto = model::DeepClone(*result.value()); + } + } + } + } + + if (min_value_proto.has_value()) { + // Reconstruct EvaluateResult from the stored proto + return EvaluateResult::NewValue(std::move(min_value_proto.value())); + } + // If only null/error/unset were encountered, return Null + return EvaluateResult::NewNull(); +} + +} // namespace core +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/core/pipeline/aggregates.h b/Firestore/core/src/core/pipeline/aggregates.h new file mode 100644 index 00000000000..f4de6bad9e9 --- /dev/null +++ b/Firestore/core/src/core/pipeline/aggregates.h @@ -0,0 +1,57 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_H_ + +#include +#include "Firestore/core/src/core/pipeline/expression.h" + +namespace firebase { +namespace firestore { +namespace core { + +class CoreMaximum : public EvaluableExpr { + public: + explicit CoreMaximum(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreMinimum : public EvaluableExpr { + public: + explicit CoreMinimum(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +} // namespace core +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_H_ diff --git a/Firestore/core/src/core/pipeline/evaluation/arithmetic.cc b/Firestore/core/src/core/pipeline/evaluation/arithmetic.cc new file mode 100644 index 00000000000..6acc7b9cb27 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/arithmetic.cc @@ -0,0 +1,204 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/core/pipeline/evaluation/arithmetic.h" +#include "Firestore/core/src/core/pipeline/evaluation/util.h" + +#include +#include + +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/util/hard_assert.h" +#include "absl/types/optional.h" + +namespace firebase { +namespace firestore { +namespace core { + +namespace { + +// Helper to create a Value proto from double +nanopb::Message DoubleValue(double val) { + google_firestore_v1_Value proto; + proto.which_value_type = google_firestore_v1_Value_double_value_tag; + proto.double_value = val; + return nanopb::MakeMessage(std::move(proto)); +} + +} // anonymous namespace + +// --- Arithmetic Implementations --- +EvaluateResult ArithmeticBase::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() >= 2, + "%s() function requires at least 2 params", expr_->name()); + + EvaluateResult current_result = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + + for (size_t i = 1; i < expr_->params().size(); ++i) { + // Check current accumulated result before evaluating next operand + if (current_result.IsErrorOrUnset()) { + // Propagate error immediately if accumulated result is error/unset + // Note: Unset is treated as Error in arithmetic according to TS logic + return EvaluateResult::NewError(); + } + // Null check happens inside ApplyOperation + + EvaluateResult next_operand = + expr_->params()[i]->ToEvaluable()->Evaluate(context, document); + + // Apply the operation + current_result = ApplyOperation(current_result, next_operand); + + // If ApplyOperation resulted in error or unset, propagate immediately as + // error + if (current_result.IsErrorOrUnset()) { + // Treat Unset from ApplyOperation as Error for propagation + return EvaluateResult::NewError(); + } + // Null is handled within the loop by ApplyOperation in the next iteration + } + + return current_result; +} + +inline EvaluateResult ArithmeticBase::ApplyOperation( + const EvaluateResult& left, const EvaluateResult& right) const { + // Mirroring TypeScript logic: + // 1. Check for Error/Unset first + if (left.IsErrorOrUnset() || right.IsErrorOrUnset()) { + return EvaluateResult::NewError(); + } + // 2. Check for Null + if (left.IsNull() || right.IsNull()) { + return EvaluateResult::NewNull(); + } + + // 3. Type check: Both must be numbers + const google_firestore_v1_Value* left_val = left.value(); + const google_firestore_v1_Value* right_val = right.value(); + if (!model::IsNumber(*left_val) || !model::IsNumber(*right_val)) { + return EvaluateResult::NewError(); // Type error + } + + // 4. Determine operation type (Integer or Double) + if (model::IsDouble(*left_val) || model::IsDouble(*right_val)) { + // Promote to double + double left_double_val = model::IsDouble(*left_val) + ? left_val->double_value + : static_cast(left_val->integer_value); + double right_double_val = + model::IsDouble(*right_val) + ? right_val->double_value + : static_cast(right_val->integer_value); + + // NaN propagation and specific error handling (like div/mod by zero) + // are handled within PerformDoubleOperation. + return PerformDoubleOperation(left_double_val, right_double_val); + + } else { + // Both are integers + absl::optional left_int_opt = model::GetInteger(*left_val); + absl::optional right_int_opt = model::GetInteger(*right_val); + // These should always succeed because we already checked IsNumber and + // excluded IsDouble. + HARD_ASSERT(left_int_opt.has_value() && right_int_opt.has_value(), + "Failed to extract integer values after IsNumber check"); + + return PerformIntegerOperation(left_int_opt.value(), right_int_opt.value()); + } +} + +EvaluateResult CoreAdd::PerformIntegerOperation(int64_t l, int64_t r) const { + auto const result = SafeAdd(l, r); + if (result.has_value()) { + return EvaluateResult::NewValue(IntValue(result.value())); + } + + return EvaluateResult::NewError(); +} + +EvaluateResult CoreAdd::PerformDoubleOperation(double l, double r) const { + return EvaluateResult::NewValue(DoubleValue(l + r)); +} + +EvaluateResult CoreSubtract::PerformIntegerOperation(int64_t l, + int64_t r) const { + auto const result = SafeSubtract(l, r); + if (result.has_value()) { + return EvaluateResult::NewValue(IntValue(result.value())); + } + + return EvaluateResult::NewError(); +} + +EvaluateResult CoreSubtract::PerformDoubleOperation(double l, double r) const { + return EvaluateResult::NewValue(DoubleValue(l - r)); +} + +EvaluateResult CoreMultiply::PerformIntegerOperation(int64_t l, + int64_t r) const { + auto const result = SafeMultiply(l, r); + if (result.has_value()) { + return EvaluateResult::NewValue(IntValue(result.value())); + } + + return EvaluateResult::NewError(); +} + +EvaluateResult CoreMultiply::PerformDoubleOperation(double l, double r) const { + return EvaluateResult::NewValue(DoubleValue(l * r)); +} + +EvaluateResult CoreDivide::PerformIntegerOperation(int64_t l, int64_t r) const { + auto const result = SafeDivide(l, r); + if (result.has_value()) { + return EvaluateResult::NewValue(IntValue(result.value())); + } + + return EvaluateResult::NewError(); +} + +EvaluateResult CoreDivide::PerformDoubleOperation(double l, double r) const { + // C++ double division handles signed zero correctly according to IEEE + // 754. +x / +0 -> +Inf -x / +0 -> -Inf +x / -0 -> -Inf -x / -0 -> +Inf + // 0 / 0 -> NaN + return EvaluateResult::NewValue(DoubleValue(l / r)); +} + +EvaluateResult CoreMod::PerformIntegerOperation(int64_t l, int64_t r) const { + auto const result = SafeMod(l, r); + if (result.has_value()) { + return EvaluateResult::NewValue(IntValue(result.value())); + } + + return EvaluateResult::NewError(); +} + +EvaluateResult CoreMod::PerformDoubleOperation(double l, double r) const { + if (r == 0.0) { + return EvaluateResult::NewValue( + DoubleValue(std::numeric_limits::quiet_NaN())); + } + // Use std::fmod for double modulo, matches C++ and Firestore semantics + return EvaluateResult::NewValue(DoubleValue(std::fmod(l, r))); +} + +} // namespace core +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/core/pipeline/evaluation/arithmetic.h b/Firestore/core/src/core/pipeline/evaluation/arithmetic.h new file mode 100644 index 00000000000..6d73f398e4f --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/arithmetic.h @@ -0,0 +1,121 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARITHMETIC_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARITHMETIC_H_ + +#include +#include "Firestore/core/src/core/pipeline/expression.h" + +namespace firebase { +namespace firestore { +namespace core { + +// --- Base Class for Arithmetic Operations --- +class ArithmeticBase : public EvaluableExpr { + public: + explicit ArithmeticBase(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + ~ArithmeticBase() override = default; + + // Implementation is inline below + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + protected: + // Performs the specific integer operation (e.g., add, subtract). + // Returns Error result on overflow or invalid operation (like div/mod by + // zero). + virtual EvaluateResult PerformIntegerOperation(int64_t lhs, + int64_t rhs) const = 0; + + // Performs the specific double operation. + // Returns Error result on invalid operation (like div/mod by zero). + virtual EvaluateResult PerformDoubleOperation(double lhs, + double rhs) const = 0; + + // Applies the arithmetic operation between two evaluated results. + // Mirrors the logic from TypeScript's applyArithmetics. + // Implementation is inline below + EvaluateResult ApplyOperation(const EvaluateResult& left, + const EvaluateResult& right) const; + + std::unique_ptr expr_; +}; +// --- End Base Class for Arithmetic Operations --- + +class CoreAdd : public ArithmeticBase { + public: + explicit CoreAdd(const api::FunctionExpr& expr) : ArithmeticBase(expr) { + } + + protected: + EvaluateResult PerformIntegerOperation(int64_t lhs, + int64_t rhs) const override; + EvaluateResult PerformDoubleOperation(double lhs, double rhs) const override; +}; + +class CoreSubtract : public ArithmeticBase { + public: + explicit CoreSubtract(const api::FunctionExpr& expr) : ArithmeticBase(expr) { + } + + protected: + EvaluateResult PerformIntegerOperation(int64_t lhs, + int64_t rhs) const override; + EvaluateResult PerformDoubleOperation(double lhs, double rhs) const override; +}; + +class CoreMultiply : public ArithmeticBase { + public: + explicit CoreMultiply(const api::FunctionExpr& expr) : ArithmeticBase(expr) { + } + + protected: + EvaluateResult PerformIntegerOperation(int64_t lhs, + int64_t rhs) const override; + EvaluateResult PerformDoubleOperation(double lhs, double rhs) const override; +}; + +class CoreDivide : public ArithmeticBase { + public: + explicit CoreDivide(const api::FunctionExpr& expr) : ArithmeticBase(expr) { + } + + protected: + EvaluateResult PerformIntegerOperation(int64_t lhs, + int64_t rhs) const override; + EvaluateResult PerformDoubleOperation(double lhs, double rhs) const override; +}; + +class CoreMod : public ArithmeticBase { + public: + explicit CoreMod(const api::FunctionExpr& expr) : ArithmeticBase(expr) { + } + + protected: + EvaluateResult PerformIntegerOperation(int64_t lhs, + int64_t rhs) const override; + EvaluateResult PerformDoubleOperation(double lhs, double rhs) const override; +}; + +} // namespace core +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARITHMETIC_H_ diff --git a/Firestore/core/src/core/pipeline/evaluation/array.cc b/Firestore/core/src/core/pipeline/evaluation/array.cc new file mode 100644 index 00000000000..dd646ea0b77 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/array.cc @@ -0,0 +1,332 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/core/pipeline/evaluation/array.h" +#include "Firestore/core/src/core/pipeline/evaluation/util.h" + +#include +#include +#include +#include + +#include "Firestore/core/src/core/pipeline/evaluation/logical.h" +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/util/hard_assert.h" + +namespace firebase { +namespace firestore { +namespace core { + +EvaluateResult CoreArrayReverse::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "array_reverse() function requires exactly 1 param"); + + std::unique_ptr operand_evaluable = + expr_->params()[0]->ToEvaluable(); + EvaluateResult evaluated = operand_evaluable->Evaluate(context, document); + + switch (evaluated.type()) { + case EvaluateResult::ResultType::kNull: { + return EvaluateResult::NewNull(); + } + case EvaluateResult::ResultType::kArray: { + std::vector> reversed_values; + if (evaluated.value()->array_value.values != nullptr) { + for (pb_size_t i = 0; i < evaluated.value()->array_value.values_count; + ++i) { + // Deep clone each element to get a new FieldValue wrapper + reversed_values.push_back( + model::DeepClone(evaluated.value()->array_value.values[i])); + } + } + + std::reverse(reversed_values.begin(), reversed_values.end()); + return EvaluateResult::NewValue( + model::ArrayValue(std::move(reversed_values))); + } + default: + return EvaluateResult::NewError(); + } +} + +EvaluateResult CoreArrayContains::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 2, + "array_contains() function requires exactly 2 params"); + + std::vector> reversed_params( + expr_->params().rbegin(), expr_->params().rend()); + auto const equal_any = + CoreEqAny(api::FunctionExpr("equal_any", std::move(reversed_params))); + return equal_any.Evaluate(context, document); +} + +EvaluateResult CoreArrayContainsAll::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 2, + "array_contains_all() function requires exactly 2 params"); + + bool found_null = false; + + // Evaluate the array to search (param 0) + std::unique_ptr array_to_search_evaluable = + expr_->params()[0]->ToEvaluable(); + EvaluateResult array_to_search = + array_to_search_evaluable->Evaluate(context, document); + + switch (array_to_search.type()) { + case EvaluateResult::ResultType::kArray: { + break; // Expected type + } + case EvaluateResult::ResultType::kNull: { + found_null = true; + break; + } + default: { + return EvaluateResult::NewError(); // Error or Unset or wrong type + } + } + + // Evaluate the elements to find (param 1) + std::unique_ptr elements_to_find_evaluable = + expr_->params()[1]->ToEvaluable(); + EvaluateResult elements_to_find = + elements_to_find_evaluable->Evaluate(context, document); + + switch (elements_to_find.type()) { + case EvaluateResult::ResultType::kArray: { + break; // Expected type + } + case EvaluateResult::ResultType::kNull: { + found_null = true; + break; + } + default: { + // Handle all other types (kError, kUnset, kBoolean, kInt, kDouble, etc.) + // as errors for the 'elements_to_find' parameter. + return EvaluateResult::NewError(); + } + } + + // If either input was null, the result is null + if (found_null) { + return EvaluateResult::NewNull(); + } + + const google_firestore_v1_Value* search_values_proto = + elements_to_find.value(); + const google_firestore_v1_Value* array_values_proto = array_to_search.value(); + bool found_null_at_least_once = false; + + // Iterate through elements we need to find (search_values) + if (search_values_proto->array_value.values != nullptr) { + for (pb_size_t i = 0; i < search_values_proto->array_value.values_count; + ++i) { + const google_firestore_v1_Value& search = + search_values_proto->array_value.values[i]; + bool found = false; + + // Iterate through the array we are searching within (array_values) + if (array_values_proto->array_value.values != nullptr) { + for (pb_size_t j = 0; j < array_values_proto->array_value.values_count; + ++j) { + const google_firestore_v1_Value& value = + array_values_proto->array_value.values[j]; + + switch (model::StrictEquals(search, value)) { + case model::StrictEqualsResult::kEq: { + found = true; + break; // Found it, break inner loop + } + case model::StrictEqualsResult::kNotEq: { + // Keep searching + break; + } + case model::StrictEqualsResult::kNull: { + found_null = true; + found_null_at_least_once = true; // Track null globally + break; + } + } + if (found) { + break; // Exit inner loop once found + } + } // End inner loop (searching array_values) + } + + // Check result for the current 'search' element + if (found) { + // true case - do nothing, we found a match, make sure all other values + // are also found + } else { + // false case - we didn't find a match, short circuit + if (!found_null) { + return EvaluateResult::NewValue( + nanopb::MakeMessage(model::FalseValue())); + } + // null case - do nothing, we found at least one null value for this + // search element, keep going + } + } // End outer loop (iterating search_values) + } + + // If we finished the outer loop + if (found_null_at_least_once) { + // If we encountered any null comparison and didn't return false earlier, + // the result is null. + return EvaluateResult::NewNull(); + } else { + // If we finished and found no nulls, and never returned false, + // it means all elements were found. + return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); + } +} + +EvaluateResult CoreArrayContainsAny::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 2, + "array_contains_any() function requires exactly 2 params"); + + bool found_null = false; + + // Evaluate the array to search (param 0) + std::unique_ptr array_to_search_evaluable = + expr_->params()[0]->ToEvaluable(); + EvaluateResult array_to_search = + array_to_search_evaluable->Evaluate(context, document); + + switch (array_to_search.type()) { + case EvaluateResult::ResultType::kArray: { + break; // Expected type + } + case EvaluateResult::ResultType::kNull: { + found_null = true; + break; + } + default: { + return EvaluateResult::NewError(); // Error or Unset or wrong type + } + } + + // Evaluate the elements to find (param 1) + std::unique_ptr elements_to_find_evaluable = + expr_->params()[1]->ToEvaluable(); + EvaluateResult elements_to_find = + elements_to_find_evaluable->Evaluate(context, document); + + switch (elements_to_find.type()) { + case EvaluateResult::ResultType::kArray: { + break; // Expected type + } + case EvaluateResult::ResultType::kNull: { + found_null = true; + break; + } + default: { + // Handle all other types (kError, kUnset, kBoolean, kInt, kDouble, etc.) + // as errors for the 'elements_to_find' parameter. + return EvaluateResult::NewError(); + } + } + + // If either input was null, the result is null + if (found_null) { + return EvaluateResult::NewNull(); + } + + const google_firestore_v1_Value* search_values_proto = + elements_to_find.value(); + const google_firestore_v1_Value* array_values_proto = array_to_search.value(); + + // Outer loop: Iterate through the array being searched + if (search_values_proto->array_value.values != nullptr) { + for (pb_size_t i = 0; i < search_values_proto->array_value.values_count; + ++i) { + const google_firestore_v1_Value& candidate = + search_values_proto->array_value.values[i]; + + // Inner loop: Iterate through the elements to find + if (array_values_proto->array_value.values != nullptr) { + for (pb_size_t j = 0; j < array_values_proto->array_value.values_count; + ++j) { + const google_firestore_v1_Value& search_element = + array_values_proto->array_value.values[j]; + + switch (model::StrictEquals(candidate, search_element)) { + case model::StrictEqualsResult::kEq: { + // Found one match, return true immediately + return EvaluateResult::NewValue( + nanopb::MakeMessage(model::TrueValue())); + } + case model::StrictEqualsResult::kNotEq: + // Continue inner loop + break; + case model::StrictEqualsResult::kNull: + // Track null, continue inner loop + found_null = true; + break; + } + } // End inner loop + } + } // End outer loop + } + + // If we finished both loops without returning true + if (found_null) { + // If we encountered any null comparison, the result is null + return EvaluateResult::NewNull(); + } else { + // If no match was found and no nulls were encountered + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } +} + +EvaluateResult CoreArrayLength::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "array_length() function requires exactly 1 param"); + + std::unique_ptr operand_evaluable = + expr_->params()[0]->ToEvaluable(); + EvaluateResult operand_result = + operand_evaluable->Evaluate(context, document); + + switch (operand_result.type()) { + case EvaluateResult::ResultType::kNull: { + return EvaluateResult::NewNull(); + } + case EvaluateResult::ResultType::kArray: { + size_t array_size = operand_result.value()->array_value.values_count; + google_firestore_v1_Value val; + val.which_value_type = google_firestore_v1_Value_integer_value_tag; + val.integer_value = array_size; + return EvaluateResult::NewValue(nanopb::MakeMessage(val)); + } + default: { + return EvaluateResult::NewError(); + } + } +} + +} // namespace core +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/core/pipeline/evaluation/array.h b/Firestore/core/src/core/pipeline/evaluation/array.h new file mode 100644 index 00000000000..4506635b282 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/array.h @@ -0,0 +1,96 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARRAY_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARRAY_H_ + +#include +#include "Firestore/core/src/core/pipeline/expression.h" + +namespace firebase { +namespace firestore { +namespace core { + +class CoreArrayReverse : public EvaluableExpr { + public: + explicit CoreArrayReverse(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreArrayContains : public EvaluableExpr { + public: + explicit CoreArrayContains(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreArrayContainsAll : public EvaluableExpr { + public: + explicit CoreArrayContainsAll(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreArrayContainsAny : public EvaluableExpr { + public: + explicit CoreArrayContainsAny(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreArrayLength : public EvaluableExpr { + public: + explicit CoreArrayLength(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +} // namespace core +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARRAY_H_ diff --git a/Firestore/core/src/core/pipeline/evaluation/comparison.cc b/Firestore/core/src/core/pipeline/evaluation/comparison.cc new file mode 100644 index 00000000000..eed478779df --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/comparison.cc @@ -0,0 +1,203 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/core/pipeline/evaluation/comparison.h" + +#include +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/util/hard_assert.h" + +namespace firebase { +namespace firestore { +namespace core { + +// --- Comparison Implementations --- + +EvaluateResult ComparisonBase::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 2, + "%s() function requires exactly 2 params", expr_->name()); + + std::unique_ptr left_evaluable = + expr_->params()[0]->ToEvaluable(); + EvaluateResult left = left_evaluable->Evaluate(context, document); + + switch (left.type()) { + case EvaluateResult::ResultType::kError: + case EvaluateResult::ResultType::kUnset: { + return EvaluateResult::NewError(); + } + default: + break; + } + + std::unique_ptr right_evaluable = + expr_->params()[1]->ToEvaluable(); + EvaluateResult right = right_evaluable->Evaluate(context, document); + switch (right.type()) { + case EvaluateResult::ResultType::kError: + case EvaluateResult::ResultType::kUnset: { + return EvaluateResult::NewError(); + } + default: + break; + } + + // Comparisons involving Null propagate Null + if (left.IsNull() || right.IsNull()) { + return EvaluateResult::NewNull(); + } + + // Operands are valid Values, proceed with specific comparison + return CompareToResult(left, right); +} + +EvaluateResult CoreEqual::CompareToResult(const EvaluateResult& left, + const EvaluateResult& right) const { + // Type mismatch always results in false for Eq + if (model::GetTypeOrder(*left.value()) != + model::GetTypeOrder(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } + // NaN == anything (including NaN) is false + if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } + + switch (model::StrictEquals(*left.value(), *right.value())) { + case model::StrictEqualsResult::kEq: + return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); + case model::StrictEqualsResult::kNotEq: + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + case model::StrictEqualsResult::kNull: + return EvaluateResult::NewNull(); + } + HARD_FAIL("Unhandled case in switch statement"); +} + +EvaluateResult CoreNotEqual::CompareToResult( + const EvaluateResult& left, const EvaluateResult& right) const { + // NaN != anything (including NaN) is true + if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); + } + // Type mismatch always results in true for Neq + if (model::GetTypeOrder(*left.value()) != + model::GetTypeOrder(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); + } + + switch (model::StrictEquals(*left.value(), *right.value())) { + case model::StrictEqualsResult::kEq: + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + case model::StrictEqualsResult::kNotEq: + return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); + case model::StrictEqualsResult::kNull: + return EvaluateResult::NewNull(); + } + HARD_FAIL("Unhandled case in switch statement"); +} + +EvaluateResult CoreLessThan::CompareToResult( + const EvaluateResult& left, const EvaluateResult& right) const { + // Type mismatch always results in false + if (model::GetTypeOrder(*left.value()) != + model::GetTypeOrder(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } + // NaN compared to anything is false + if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } + + bool result = model::Compare(*left.value(), *right.value()) == + util::ComparisonResult::Ascending; + return EvaluateResult::NewValue( + nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); +} + +EvaluateResult CoreLessThanOrEqual::CompareToResult( + const EvaluateResult& left, const EvaluateResult& right) const { + // Type mismatch always results in false + if (model::GetTypeOrder(*left.value()) != + model::GetTypeOrder(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } + // NaN compared to anything is false + if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } + + // Check for equality first using StrictEquals + if (model::StrictEquals(*left.value(), *right.value()) == + model::StrictEqualsResult::kEq) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); + } + + // If not equal, perform standard comparison + bool result = model::Compare(*left.value(), *right.value()) == + util::ComparisonResult::Ascending; + return EvaluateResult::NewValue( + nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); +} + +EvaluateResult CoreGreaterThan::CompareToResult( + const EvaluateResult& left, const EvaluateResult& right) const { + // Type mismatch always results in false + if (model::GetTypeOrder(*left.value()) != + model::GetTypeOrder(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } + // NaN compared to anything is false + if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } + + bool result = model::Compare(*left.value(), *right.value()) == + util::ComparisonResult::Descending; + return EvaluateResult::NewValue( + nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); +} + +EvaluateResult CoreGreaterThanOrEqual::CompareToResult( + const EvaluateResult& left, const EvaluateResult& right) const { + // Type mismatch always results in false + if (model::GetTypeOrder(*left.value()) != + model::GetTypeOrder(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } + // NaN compared to anything is false + if (model::IsNaNValue(*left.value()) || model::IsNaNValue(*right.value())) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } + + // Check for equality first using StrictEquals + if (model::StrictEquals(*left.value(), *right.value()) == + model::StrictEqualsResult::kEq) { + return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); + } + + // If not equal, perform standard comparison + bool result = model::Compare(*left.value(), *right.value()) == + util::ComparisonResult::Descending; + return EvaluateResult::NewValue( + nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); +} + +} // namespace core +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/core/pipeline/evaluation/comparison.h b/Firestore/core/src/core/pipeline/evaluation/comparison.h new file mode 100644 index 00000000000..7404f4d38ce --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/comparison.h @@ -0,0 +1,116 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_COMPARISON_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_COMPARISON_H_ + +#include +#include "Firestore/core/src/core/pipeline/expression.h" + +namespace firebase { +namespace firestore { +namespace core { + +/** Base class for binary comparison expressions (==, !=, <, <=, >, >=). */ +class ComparisonBase : public EvaluableExpr { + public: + explicit ComparisonBase(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + protected: + /** + * Performs the specific comparison logic after operands have been evaluated + * and basic checks (Error, Unset, Null) have passed. + */ + virtual EvaluateResult CompareToResult(const EvaluateResult& left, + const EvaluateResult& right) const = 0; + + std::unique_ptr expr_; +}; + +class CoreEqual : public ComparisonBase { + public: + explicit CoreEqual(const api::FunctionExpr& expr) : ComparisonBase(expr) { + } + + protected: + EvaluateResult CompareToResult(const EvaluateResult& left, + const EvaluateResult& right) const override; +}; + +class CoreNotEqual : public ComparisonBase { + public: + explicit CoreNotEqual(const api::FunctionExpr& expr) : ComparisonBase(expr) { + } + + protected: + EvaluateResult CompareToResult(const EvaluateResult& left, + const EvaluateResult& right) const override; +}; + +class CoreLessThan : public ComparisonBase { + public: + explicit CoreLessThan(const api::FunctionExpr& expr) : ComparisonBase(expr) { + } + + protected: + EvaluateResult CompareToResult(const EvaluateResult& left, + const EvaluateResult& right) const override; +}; + +class CoreLessThanOrEqual : public ComparisonBase { + public: + explicit CoreLessThanOrEqual(const api::FunctionExpr& expr) + : ComparisonBase(expr) { + } + + protected: + EvaluateResult CompareToResult(const EvaluateResult& left, + const EvaluateResult& right) const override; +}; + +class CoreGreaterThan : public ComparisonBase { + public: + explicit CoreGreaterThan(const api::FunctionExpr& expr) + : ComparisonBase(expr) { + } + + protected: + EvaluateResult CompareToResult(const EvaluateResult& left, + const EvaluateResult& right) const override; +}; + +class CoreGreaterThanOrEqual : public ComparisonBase { + public: + explicit CoreGreaterThanOrEqual(const api::FunctionExpr& expr) + : ComparisonBase(expr) { + } + + protected: + EvaluateResult CompareToResult(const EvaluateResult& left, + const EvaluateResult& right) const override; +}; + +} // namespace core +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_COMPARISON_H_ diff --git a/Firestore/core/src/core/pipeline/evaluation/logical.cc b/Firestore/core/src/core/pipeline/evaluation/logical.cc new file mode 100644 index 00000000000..4e859595e04 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/logical.cc @@ -0,0 +1,282 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/core/pipeline/evaluation/logical.h" + +#include +#include +#include + +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/util/hard_assert.h" + +namespace firebase { +namespace firestore { +namespace core { + +// --- Logical Expression Implementations --- + +EvaluateResult CoreAnd::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + bool has_null = false; + bool has_error = false; + for (const auto& param : expr_->params()) { + EvaluateResult const result = + param->ToEvaluable()->Evaluate(context, document); + switch (result.type()) { + case EvaluateResult::ResultType::kBoolean: + if (!result.value()->boolean_value) { + // Short-circuit on false + return EvaluateResult::NewValue( + nanopb::MakeMessage(model::FalseValue())); + } + break; // Break if true + case EvaluateResult::ResultType::kNull: + has_null = true; // Track null, continue evaluation + break; + default: + has_error = true; + break; + } + } + + if (has_error) { + return EvaluateResult::NewError(); // If any operand results in error + } + + if (has_null) { + return EvaluateResult::NewNull(); // If null was encountered, result is + // null + } + + return EvaluateResult::NewValue( + nanopb::MakeMessage(model::TrueValue())); // Otherwise, result is true +} + +EvaluateResult CoreOr::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + bool has_null = false; + bool has_error = false; + for (const auto& param : expr_->params()) { + EvaluateResult const result = + param->ToEvaluable()->Evaluate(context, document); + switch (result.type()) { + case EvaluateResult::ResultType::kBoolean: + if (result.value()->boolean_value) { + // Short-circuit on true + return EvaluateResult::NewValue( + nanopb::MakeMessage(model::TrueValue())); + } + break; // Continue if false + case EvaluateResult::ResultType::kNull: + has_null = true; // Track null, continue evaluation + break; + default: + has_error = true; + break; + } + } + + // If loop completes without returning true: + if (has_error) { + return EvaluateResult::NewError(); + } + + if (has_null) { + return EvaluateResult::NewNull(); + } + + return EvaluateResult::NewValue( + nanopb::MakeMessage(model::FalseValue())); // Otherwise, result is false +} + +EvaluateResult CoreXor::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + bool current_xor_result = false; + bool has_null = false; + for (const auto& param : expr_->params()) { + EvaluateResult const evaluated = + param->ToEvaluable()->Evaluate(context, document); + switch (evaluated.type()) { + case EvaluateResult::ResultType::kBoolean: { + bool operand_value = evaluated.value()->boolean_value; + // XOR logic: result = result ^ operand + current_xor_result = current_xor_result != operand_value; + break; + } + case EvaluateResult::ResultType::kNull: { + has_null = true; + break; + } + default: { + // Any non-boolean, non-null operand results in error + return EvaluateResult::NewError(); + } + } + } + + if (has_null) { + return EvaluateResult::NewNull(); + } + return EvaluateResult::NewValue(nanopb::MakeMessage( + current_xor_result ? model::TrueValue() : model::FalseValue())); +} + +EvaluateResult CoreCond::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 3, + "cond() function requires exactly 3 params"); + + EvaluateResult condition = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + + switch (condition.type()) { + case EvaluateResult::ResultType::kBoolean: { + if (condition.value()->boolean_value) { + // Condition is true, evaluate the second parameter + return expr_->params()[1]->ToEvaluable()->Evaluate(context, document); + } else { + // Condition is false, evaluate the third parameter + return expr_->params()[2]->ToEvaluable()->Evaluate(context, document); + } + } + case EvaluateResult::ResultType::kNull: { + // Condition is null, evaluate the third parameter (false case) + return expr_->params()[2]->ToEvaluable()->Evaluate(context, document); + } + default: + // Condition is error, unset, or non-boolean/non-null type + return EvaluateResult::NewError(); + } +} + +EvaluateResult CoreEqAny::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT( + expr_->params().size() == 2, + "equal_any() function requires exactly 2 params (search value and " + "array value)"); + + bool found_null = false; + + // Evaluate the search value (param 0) + EvaluateResult const search_result = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + switch (search_result.type()) { + case EvaluateResult::ResultType::kNull: { + found_null = true; + break; + } + case EvaluateResult::ResultType::kError: + case EvaluateResult::ResultType::kUnset: + return EvaluateResult::NewError(); // Error/Unset search value is error + default: + break; // Valid value + } + + EvaluateResult const array_result = + expr_->params()[1]->ToEvaluable()->Evaluate(context, document); + switch (array_result.type()) { + case EvaluateResult::ResultType::kNull: { + found_null = true; + break; + } + case EvaluateResult::ResultType::kArray: { + break; + } + default: + return EvaluateResult::NewError(); + } + + if (found_null) { + return EvaluateResult::NewNull(); + } + + for (size_t i = 0; i < array_result.value()->array_value.values_count; ++i) { + const google_firestore_v1_Value& candidate = + array_result.value()->array_value.values[i]; + switch (model::StrictEquals(*search_result.value(), candidate)) { + case model::StrictEqualsResult::kEq: { + return EvaluateResult::NewValue( + nanopb::MakeMessage(model::TrueValue())); + } + case model::StrictEqualsResult::kNotEq: { + break; + } + case model::StrictEqualsResult::kNull: { + found_null = true; + break; + } + } + } + + if (found_null) { + return EvaluateResult::NewNull(); + } + + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); +} + +EvaluateResult CoreNotEqAny::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT( + expr_->params().size() == 2, + "not_eq_any() function requires exactly 2 params (search value and " + "array value)"); + + CoreNot equivalent(api::FunctionExpr( + "not", + {std::make_shared("equal_any", expr_->params())})); + return equivalent.Evaluate(context, document); +} + +EvaluateResult CoreNot::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "not() function requires exactly 1 param"); + + std::unique_ptr operand_evaluable = + expr_->params()[0]->ToEvaluable(); + EvaluateResult evaluated = operand_evaluable->Evaluate(context, document); + + switch (evaluated.type()) { + case EvaluateResult::ResultType::kBoolean: { + // Negate the boolean value + bool original_value = evaluated.value()->boolean_value; + return EvaluateResult::NewValue(nanopb::MakeMessage( + original_value ? model::FalseValue() : model::TrueValue())); + } + case EvaluateResult::ResultType::kNull: { + // NOT(NULL) -> NULL + return EvaluateResult::NewNull(); + } + default: { + // NOT applied to non-boolean, non-null is an error + return EvaluateResult::NewError(); + } + } +} + +} // namespace core +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/core/pipeline/evaluation/logical.h b/Firestore/core/src/core/pipeline/evaluation/logical.h new file mode 100644 index 00000000000..6aa637ab2ab --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/logical.h @@ -0,0 +1,122 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_LOGICAL_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_LOGICAL_H_ + +#include +#include "Firestore/core/src/core/pipeline/expression.h" + +namespace firebase { +namespace firestore { +namespace core { + +class CoreAnd : public EvaluableExpr { + public: + explicit CoreAnd(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreOr : public EvaluableExpr { + public: + explicit CoreOr(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreXor : public EvaluableExpr { + public: + explicit CoreXor(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreCond : public EvaluableExpr { + public: + explicit CoreCond(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreEqAny : public EvaluableExpr { + public: + explicit CoreEqAny(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreNotEqAny : public EvaluableExpr { + public: + explicit CoreNotEqAny(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreNot : public EvaluableExpr { + public: + explicit CoreNot(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +} // namespace core +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_LOGICAL_H_ diff --git a/Firestore/core/src/core/pipeline/evaluation/map.cc b/Firestore/core/src/core/pipeline/evaluation/map.cc new file mode 100644 index 00000000000..75a4b9c9285 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/map.cc @@ -0,0 +1,88 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/core/pipeline/evaluation/map.h" + +#include +#include + +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/util/hard_assert.h" +#include "absl/types/optional.h" + +namespace firebase { +namespace firestore { +namespace core { + +EvaluateResult CoreMapGet::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 2, + "map_get() function requires exactly 2 params (map and key)"); + + // Evaluate the map operand (param 0) + std::unique_ptr map_evaluable = + expr_->params()[0]->ToEvaluable(); + EvaluateResult map_result = map_evaluable->Evaluate(context, document); + + switch (map_result.type()) { + case EvaluateResult::ResultType::kUnset: { + // If the map itself is unset, the result is unset + return EvaluateResult::NewUnset(); + } + case EvaluateResult::ResultType::kMap: { + // Expected type, continue + break; + } + default: { + // Any other type (including Null, Error) is an error + return EvaluateResult::NewError(); + } + } + + // Evaluate the key operand (param 1) + std::unique_ptr key_evaluable = + expr_->params()[1]->ToEvaluable(); + EvaluateResult key_result = key_evaluable->Evaluate(context, document); + + absl::optional key_string; + switch (key_result.type()) { + case EvaluateResult::ResultType::kString: { + key_string = nanopb::MakeString(key_result.value()->string_value); + HARD_ASSERT(key_string.has_value(), "Failed to extract string key"); + break; + } + default: { + // Key must be a string, otherwise it's an error + return EvaluateResult::NewError(); + } + } + + // Look up the field in the map value + const auto* entry = model::FindEntry(*map_result.value(), key_string.value()); + + if (entry != nullptr) { + // Key found, return a deep clone of the value + return EvaluateResult::NewValue(model::DeepClone(entry->value)); + } else { + // Key not found, return Unset + return EvaluateResult::NewUnset(); + } +} + +} // namespace core +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/core/pipeline/evaluation/map.h b/Firestore/core/src/core/pipeline/evaluation/map.h new file mode 100644 index 00000000000..2d615cdf9a3 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/map.h @@ -0,0 +1,44 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_MAP_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_MAP_H_ + +#include +#include "Firestore/core/src/core/pipeline/expression.h" + +namespace firebase { +namespace firestore { +namespace core { + +class CoreMapGet : public EvaluableExpr { + public: + explicit CoreMapGet(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +} // namespace core +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_MAP_H_ diff --git a/Firestore/core/src/core/pipeline/evaluation/string.cc b/Firestore/core/src/core/pipeline/evaluation/string.cc new file mode 100644 index 00000000000..d993980f566 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/string.cc @@ -0,0 +1,520 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/core/pipeline/evaluation/string.h" +#include "Firestore/core/src/core/pipeline/evaluation/util.h" + +#include +#include +#include +#include +#include +#include + +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/util/hard_assert.h" +#include "absl/strings/match.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/strip.h" +#include "re2/re2.h" + +namespace firebase { +namespace firestore { +namespace core { + +namespace { + +/** + * @brief Validates a string as UTF-8 and process the Unicode code points. + * + * Iterates through the byte sequence of the input string, performing + * full UTF-8 validation checks: + * - Correct number of continuation bytes. + * - Correct format of continuation bytes (10xxxxxx). + * - No overlong encodings (e.g., encoding '/' as 2 bytes). + * - Decoded code points are within the valid Unicode range + * (U+0000-U+D7FF and U+E000-U+10FFFF), excluding surrogates. + * + * @tparam T The type of the result accumulator. + * @param s The input string (byte sequence) to validate. + * @param result A pointer to the result accumulator, updated by `func`. + * @param func A function `void(T* result, uint32_t code_point, + * absl::string_view utf8_bytes)` called for each valid code point, providing + * the code point and its UTF-8 byte representation. + * @return `true` if the string is valid UTF-8, `false` otherwise. + */ +template +bool ProcessUtf8(const std::string& s, + T* result, + std::function func) { + size_t i = 0; + const size_t len = s.size(); + const unsigned char* data = reinterpret_cast(s.data()); + + while (i < len) { + uint32_t code_point = 0; // To store the decoded code point + int num_bytes = 0; + const unsigned char start_byte = data[i]; + + // 1. Determine expected sequence length and initial code point bits + if ((start_byte & 0x80) == 0) { // 1-byte sequence (ASCII 0xxxxxxx) + num_bytes = 1; + code_point = start_byte; + // Overlong check: Not possible for 1-byte sequences + // Range check: ASCII is always valid (0x00-0x7F) + } else if ((start_byte & 0xE0) == 0xC0) { // 2-byte sequence (110xxxxx) + num_bytes = 2; + code_point = start_byte & 0x1F; // Mask out 110xxxxx + // Overlong check: Must not represent code points < 0x80 + // Also, C0 and C1 are specifically invalid start bytes + if (start_byte < 0xC2) { + return false; // C0, C1 are invalid starts + } + } else if ((start_byte & 0xF0) == 0xE0) { // 3-byte sequence (1110xxxx) + num_bytes = 3; + code_point = start_byte & 0x0F; // Mask out 1110xxxx + } else if ((start_byte & 0xF8) == 0xF0) { // 4-byte sequence (11110xxx) + num_bytes = 4; + code_point = + start_byte & 0x07; // Mask out 11110xxx + // Overlong check: Must not represent code points + // < 0x10000 Range check: Must not represent code + // points > 0x10FFFF F4 90.. BF.. is > 0x10FFFF + if (start_byte > 0xF4) { + return false; + } + } else { + return false; // Invalid start byte (e.g., 10xxxxxx or > F4) + } + + // 2. Check for incomplete sequence + if (i + num_bytes > len) { + return false; // Sequence extends beyond string end + } + + // 3. Check and process continuation bytes (if any) + for (int j = 1; j < num_bytes; ++j) { + const unsigned char continuation_byte = data[i + j]; + if ((continuation_byte & 0xC0) != 0x80) { + return false; // Not a valid continuation byte (10xxxxxx) + } + // Combine bits into the code point + code_point = (code_point << 6) | (continuation_byte & 0x3F); + } + + // 4. Perform Overlong and Range Checks based on the fully decoded + // code_point + if (num_bytes == 2 && code_point < 0x80) { + return false; // Overlong encoding (should have been 1 byte) + } + if (num_bytes == 3 && code_point < 0x800) { + // Specific check for 0xE0 0x80..0x9F .. sequences (overlong) + if (start_byte == 0xE0 && (data[i + 1] & 0xFF) < 0xA0) { + return false; + } + return false; // Overlong encoding (should have been 1 or 2 bytes) + } + if (num_bytes == 4 && code_point < 0x10000) { + // Specific check for 0xF0 0x80..0x8F .. sequences (overlong) + if (start_byte == 0xF0 && (data[i + 1] & 0xFF) < 0x90) { + return false; + } + return false; // Overlong encoding (should have been 1, 2 or 3 bytes) + } + + // Check for surrogates (U+D800 to U+DFFF) + if (code_point >= 0xD800 && code_point <= 0xDFFF) { + return false; + } + + // Check for code points beyond the Unicode maximum (U+10FFFF) + if (code_point > 0x10FFFF) { + // Specific check for 0xF4 90..BF .. sequences (> U+10FFFF) + if (start_byte == 0xF4 && (data[i + 1] & 0xFF) > 0x8F) { + return false; + } + return false; + } + + // 5. If all checks passed, call the function and advance index + absl::string_view utf8_bytes(s.data() + i, num_bytes); + func(result, code_point, utf8_bytes); + i += num_bytes; + } + + return true; // String is valid UTF-8 +} + +// Helper function to convert SQL LIKE patterns to RE2 regex patterns. +// Handles % (matches any sequence of zero or more characters) +// and _ (matches any single character). +// Escapes other regex special characters. +std::string LikeToRegex(const std::string& like_pattern) { + std::string regex_pattern = "^"; // Anchor at the start + for (char c : like_pattern) { + switch (c) { + case '%': + regex_pattern += ".*"; + break; + case '_': + regex_pattern += "."; + break; + // Escape RE2 special characters + case '\\': + case '.': + case '*': + case '+': + case '?': + case '(': + case ')': + case '|': + case '{': + case '}': + case '[': + case ']': + case '^': + case '$': + regex_pattern += '\\'; + regex_pattern += c; + break; + default: + regex_pattern += c; + break; + } + } + regex_pattern += '$'; // Anchor at the end + return regex_pattern; +} + +} // anonymous namespace + +EvaluateResult StringSearchBase::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 2, + "%s() function requires exactly 2 params", expr_->name()); + + bool has_null = false; + EvaluateResult op1 = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + switch (op1.type()) { + case EvaluateResult::ResultType::kString: { + break; + } + case EvaluateResult::ResultType::kNull: { + has_null = true; + break; + } + default: { + return EvaluateResult::NewError(); + } + } + + EvaluateResult op2 = + expr_->params()[1]->ToEvaluable()->Evaluate(context, document); + switch (op2.type()) { + case EvaluateResult::ResultType::kString: { + break; + } + case EvaluateResult::ResultType::kNull: { + has_null = true; + break; + } + default: { + return EvaluateResult::NewError(); + } + } + + // Null propagation + if (has_null) { + return EvaluateResult::NewNull(); + } + + // Both operands are valid strings, perform the specific search + std::string value_str = nanopb::MakeString(op1.value()->string_value); + std::string search_str = nanopb::MakeString(op2.value()->string_value); + + return PerformSearch(value_str, search_str); +} + +EvaluateResult CoreRegexContains::PerformSearch( + const std::string& value, const std::string& search) const { + re2::RE2 re(search); + if (!re.ok()) { + // TODO(wuandy): Log warning about invalid regex? + return EvaluateResult::NewError(); + } + bool result = RE2::PartialMatch(value, re); + return EvaluateResult::NewValue( + nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); +} + +EvaluateResult CoreRegexMatch::PerformSearch(const std::string& value, + const std::string& search) const { + re2::RE2 re(search); + if (!re.ok()) { + // TODO(wuandy): Log warning about invalid regex? + return EvaluateResult::NewError(); + } + bool result = RE2::FullMatch(value, re); + return EvaluateResult::NewValue( + nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); +} + +EvaluateResult CoreLike::PerformSearch(const std::string& value, + const std::string& search) const { + std::string regex_pattern = LikeToRegex(search); + re2::RE2 re(regex_pattern); + // LikeToRegex should ideally produce valid regex, but check anyway. + if (!re.ok()) { + // TODO(wuandy): Log warning about failed LIKE conversion? + return EvaluateResult::NewError(); + } + // LIKE implies matching the entire string + bool result = RE2::FullMatch(value, re); + return EvaluateResult::NewValue( + nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); +} + +EvaluateResult CoreByteLength::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "byte_length() requires exactly 1 param"); + EvaluateResult evaluated = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + + switch (evaluated.type()) { + case EvaluateResult::ResultType::kString: { + const auto str = nanopb::MakeString(evaluated.value()->string_value); + // Validate UTF-8 using the generic function with a no-op lambda + bool dummy_result = false; // Result accumulator not needed here + bool is_valid_utf8 = ProcessUtf8( + str, &dummy_result, + [](bool*, uint32_t, absl::string_view) { /* no-op */ }); + + if (is_valid_utf8) { + google_firestore_v1_Value val; + val.which_value_type = google_firestore_v1_Value_integer_value_tag; + val.integer_value = str.size(); + return EvaluateResult::NewValue(nanopb::MakeMessage(val)); + } else { + return EvaluateResult::NewError(); // Invalid UTF-8 + } + } + case EvaluateResult::ResultType::kBytes: { + const size_t len = evaluated.value()->bytes_value == nullptr + ? 0 + : evaluated.value()->bytes_value->size; + google_firestore_v1_Value val; + val.which_value_type = google_firestore_v1_Value_integer_value_tag; + val.integer_value = len; + return EvaluateResult::NewValue(nanopb::MakeMessage(val)); + } + case EvaluateResult::ResultType::kNull: + return EvaluateResult::NewNull(); + default: + return EvaluateResult::NewError(); // Type mismatch or Error/Unset + } +} + +EvaluateResult CoreCharLength::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "char_length() requires exactly 1 param"); + EvaluateResult evaluated = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + + switch (evaluated.type()) { + case EvaluateResult::ResultType::kString: { + const auto str = nanopb::MakeString(evaluated.value()->string_value); + // Count codepoints using the generic function + int char_count = 0; + bool is_valid_utf8 = ProcessUtf8( + str, &char_count, + [](int* count, uint32_t, absl::string_view) { (*count)++; }); + + if (is_valid_utf8) { + google_firestore_v1_Value val; + val.which_value_type = google_firestore_v1_Value_integer_value_tag; + val.integer_value = char_count; + return EvaluateResult::NewValue(nanopb::MakeMessage(val)); + } else { + return EvaluateResult::NewError(); // Invalid UTF-8 + } + } + case EvaluateResult::ResultType::kNull: + return EvaluateResult::NewNull(); + default: + return EvaluateResult::NewError(); // Type mismatch or Error/Unset + } +} + +EvaluateResult CoreStringConcat::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + std::string result_string; + + bool found_null = false; + for (const auto& param : expr_->params()) { + EvaluateResult evaluated = + param->ToEvaluable()->Evaluate(context, document); + switch (evaluated.type()) { + case EvaluateResult::ResultType::kString: { + absl::StrAppend(&result_string, + nanopb::MakeString(evaluated.value()->string_value)); + break; + } + case EvaluateResult::ResultType::kNull: { + found_null = true; + break; + } + default: + return EvaluateResult::NewError(); // Type mismatch or Error/Unset + } + } + + if (found_null) { + return EvaluateResult::NewNull(); + } + + return EvaluateResult::NewValue(model::StringValue(result_string)); +} + +EvaluateResult CoreEndsWith::PerformSearch(const std::string& value, + const std::string& search) const { + // Use absl::EndsWith + bool result = absl::EndsWith(value, search); + return EvaluateResult::NewValue( + nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); +} + +EvaluateResult CoreStartsWith::PerformSearch(const std::string& value, + const std::string& search) const { + // Use absl::StartsWith + bool result = absl::StartsWith(value, search); + return EvaluateResult::NewValue( + nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); +} + +EvaluateResult CoreStringContains::PerformSearch( + const std::string& value, const std::string& search) const { + // Use absl::StrContains + bool result = absl::StrContains(value, search); + return EvaluateResult::NewValue( + nanopb::MakeMessage(result ? model::TrueValue() : model::FalseValue())); +} + +EvaluateResult CoreToLower::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "to_lower() requires exactly 1 param"); + EvaluateResult evaluated = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + + switch (evaluated.type()) { + case EvaluateResult::ResultType::kString: { + std::locale locale{"en_US.UTF-8"}; + std::string str = nanopb::MakeString(evaluated.value()->string_value); + std::transform(str.begin(), str.end(), str.begin(), + [&locale](char c) { return std::tolower(c, locale); }); + return EvaluateResult::NewValue(model::StringValue(str)); + } + case EvaluateResult::ResultType::kNull: + return EvaluateResult::NewNull(); + default: + return EvaluateResult::NewError(); // Type mismatch or Error/Unset + } +} +EvaluateResult CoreToUpper::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "to_upper() requires exactly 1 param"); + EvaluateResult evaluated = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + + switch (evaluated.type()) { + case EvaluateResult::ResultType::kString: { + std::locale locale{"en_US.UTF-8"}; + std::string str = nanopb::MakeString(evaluated.value()->string_value); + std::transform(str.begin(), str.end(), str.begin(), + [&locale](char c) { return std::toupper(c, locale); }); + return EvaluateResult::NewValue(model::StringValue(str)); + } + case EvaluateResult::ResultType::kNull: + return EvaluateResult::NewNull(); + default: + return EvaluateResult::NewError(); // Type mismatch or Error/Unset + } +} + +EvaluateResult CoreTrim::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, "trim() requires exactly 1 param"); + EvaluateResult evaluated = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + + switch (evaluated.type()) { + case EvaluateResult::ResultType::kString: { + std::string str = nanopb::MakeString(evaluated.value()->string_value); + absl::string_view trimmed_view = absl::StripAsciiWhitespace(str); + return EvaluateResult::NewValue(model::StringValue(trimmed_view)); + } + case EvaluateResult::ResultType::kNull: + return EvaluateResult::NewNull(); + default: + return EvaluateResult::NewError(); // Type mismatch or Error/Unset + } +} + +EvaluateResult CoreStringReverse::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "reverse() requires exactly 1 param"); + EvaluateResult evaluated = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + + switch (evaluated.type()) { + case EvaluateResult::ResultType::kString: { + std::string reversed; + bool is_valid_utf8 = ProcessUtf8( + nanopb::MakeString(evaluated.value()->string_value), &reversed, + [](std::string* reversed_str, uint32_t /*code_point*/, + absl::string_view utf8_bytes) { + reversed_str->insert(0, utf8_bytes.data(), utf8_bytes.size()); + }); + + if (is_valid_utf8) { + return EvaluateResult::NewValue(model::StringValue(reversed)); + } + + return EvaluateResult::NewError(); + } + case EvaluateResult::ResultType::kNull: + return EvaluateResult::NewNull(); + default: + return EvaluateResult::NewError(); // Type mismatch or Error/Unset + } +} + +} // namespace core +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/core/pipeline/evaluation/string.h b/Firestore/core/src/core/pipeline/evaluation/string.h new file mode 100644 index 00000000000..9f610cad486 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/string.h @@ -0,0 +1,211 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_STRING_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_STRING_H_ + +#include +#include +#include "Firestore/core/src/core/pipeline/expression.h" + +namespace firebase { +namespace firestore { +namespace core { + +/** Base class for binary string search functions (starts_with, ends_with, + * str_contains). */ +class StringSearchBase : public EvaluableExpr { + public: + explicit StringSearchBase(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + protected: + /** + * Performs the specific string search logic after operands have been + * evaluated and basic checks (Error, Unset, Null, Type) have passed. + */ + virtual EvaluateResult PerformSearch(const std::string& value, + const std::string& search) const = 0; + + std::unique_ptr expr_; +}; + +class CoreByteLength : public EvaluableExpr { + public: + explicit CoreByteLength(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreCharLength : public EvaluableExpr { + public: + explicit CoreCharLength(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreStringConcat : public EvaluableExpr { + public: + explicit CoreStringConcat(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreEndsWith : public StringSearchBase { + public: + explicit CoreEndsWith(const api::FunctionExpr& expr) + : StringSearchBase(expr) { + } + + protected: + EvaluateResult PerformSearch(const std::string& value, + const std::string& search) const override; +}; + +class CoreStartsWith : public StringSearchBase { + public: + explicit CoreStartsWith(const api::FunctionExpr& expr) + : StringSearchBase(expr) { + } + + protected: + EvaluateResult PerformSearch(const std::string& value, + const std::string& search) const override; +}; + +class CoreStringContains : public StringSearchBase { + public: + explicit CoreStringContains(const api::FunctionExpr& expr) + : StringSearchBase(expr) { + } + + protected: + EvaluateResult PerformSearch(const std::string& value, + const std::string& search) const override; +}; + +class CoreToLower : public EvaluableExpr { + public: + explicit CoreToLower(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreToUpper : public EvaluableExpr { + public: + explicit CoreToUpper(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreTrim : public EvaluableExpr { + public: + explicit CoreTrim(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreStringReverse : public EvaluableExpr { + public: + explicit CoreStringReverse(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreRegexContains : public StringSearchBase { + public: + explicit CoreRegexContains(const api::FunctionExpr& expr) + : StringSearchBase(expr) { + } + + protected: + EvaluateResult PerformSearch(const std::string& value, + const std::string& search) const override; +}; + +class CoreRegexMatch : public StringSearchBase { + public: + explicit CoreRegexMatch(const api::FunctionExpr& expr) + : StringSearchBase(expr) { + } + + protected: + EvaluateResult PerformSearch(const std::string& value, + const std::string& search) const override; +}; + +class CoreLike : public StringSearchBase { + public: + explicit CoreLike(const api::FunctionExpr& expr) : StringSearchBase(expr) { + } + + protected: + EvaluateResult PerformSearch(const std::string& value, + const std::string& search) const override; +}; + +} // namespace core +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_STRING_H_ diff --git a/Firestore/core/src/core/pipeline/evaluation/timestamp.cc b/Firestore/core/src/core/pipeline/evaluation/timestamp.cc new file mode 100644 index 00000000000..e30815c5f68 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/timestamp.cc @@ -0,0 +1,303 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/core/pipeline/evaluation/timestamp.h" + +#include + +#include "Firestore/core/src/core/pipeline/evaluation/util.h" +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/util/hard_assert.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" + +namespace firebase { +namespace firestore { +namespace core { + +namespace { + +// --- Timestamp Constants --- +// 0001-01-01T00:00:00Z +constexpr int64_t kTimestampMinSeconds = -62135596800LL; +// 9999-12-31T23:59:59Z (max seconds part) +constexpr int64_t kTimestampMaxSeconds = 253402300799LL; +// Max nanoseconds part +constexpr int32_t kTimestampMaxNanos = 999999999; + +constexpr int64_t kMillisecondsPerSecond = 1000LL; +constexpr int64_t kMicrosecondsPerSecond = 1000000LL; +constexpr int64_t kNanosecondsPerMicrosecond = 1000LL; +constexpr int64_t kNanosecondsPerSecond = 1000000000LL; + +// 0001-01-01T00:00:00.000000Z +constexpr int64_t kTimestampMinMicroseconds = + kTimestampMinSeconds * kMicrosecondsPerSecond; +// 9999-12-31T23:59:59.999999Z +constexpr int64_t kTimestampMaxMicroseconds = + kTimestampMaxSeconds * kMicrosecondsPerSecond + 999999LL; + +EvaluateResult MicrosToTimestampResult(int64_t value) { + if (value < kTimestampMinMicroseconds || value > kTimestampMaxMicroseconds) { + return EvaluateResult::NewError(); + } + int64_t seconds = value / kMicrosecondsPerSecond; + int32_t nanos = (value % kMicrosecondsPerSecond) * kNanosecondsPerMicrosecond; + if (nanos < 0) { + seconds--; + nanos += kNanosecondsPerSecond; + } + if (nanos > kTimestampMaxNanos) { // Explicitly use kTimestampMaxNanos + return EvaluateResult::NewError(); + } + google_firestore_v1_Value result; + result.which_value_type = google_firestore_v1_Value_timestamp_value_tag; + result.timestamp_value.seconds = seconds; + result.timestamp_value.nanos = nanos; + return EvaluateResult::NewValue(nanopb::MakeMessage(result)); +} + +} // namespace + +CoreUnixMicrosToTimestamp::CoreUnixMicrosToTimestamp( + const api::FunctionExpr& expr) + : UnixToTimestampBase(expr) { +} + +CoreUnixMillisToTimestamp::CoreUnixMillisToTimestamp( + const api::FunctionExpr& expr) + : UnixToTimestampBase(expr) { +} + +CoreUnixSecondsToTimestamp::CoreUnixSecondsToTimestamp( + const api::FunctionExpr& expr) + : UnixToTimestampBase(expr) { +} + +CoreTimestampToUnixMicros::CoreTimestampToUnixMicros( + const api::FunctionExpr& expr) + : TimestampToUnixBase(expr) { +} + +CoreTimestampToUnixMillis::CoreTimestampToUnixMillis( + const api::FunctionExpr& expr) + : TimestampToUnixBase(expr) { +} + +CoreTimestampToUnixSeconds::CoreTimestampToUnixSeconds( + const api::FunctionExpr& expr) + : TimestampToUnixBase(expr) { +} + +CoreTimestampAdd::CoreTimestampAdd(const api::FunctionExpr& expr) + : TimestampArithmeticBase(expr) { +} + +CoreTimestampSub::CoreTimestampSub(const api::FunctionExpr& expr) + : TimestampArithmeticBase(expr) { +} + +EvaluateResult UnixToTimestampBase::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "Unix to Timestamp conversion requires exactly 1 param"); + EvaluateResult evaluated = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + switch (evaluated.type()) { + case EvaluateResult::ResultType::kInt: { + return ToTimestamp(evaluated.value()->integer_value); + } + case EvaluateResult::ResultType::kNull: + return EvaluateResult::NewNull(); + default: + return EvaluateResult::NewError(); + } +} + +EvaluateResult CoreUnixMicrosToTimestamp::ToTimestamp(int64_t value) const { + return MicrosToTimestampResult(value); +} + +EvaluateResult CoreUnixMillisToTimestamp::ToTimestamp(int64_t value) const { + constexpr int64_t kTimestampMinMilliseconds = + kTimestampMinSeconds * kMillisecondsPerSecond; + constexpr int64_t kTimestampMaxMilliseconds = + kTimestampMaxSeconds * kMillisecondsPerSecond + 999LL; + if (value < kTimestampMinMilliseconds || value > kTimestampMaxMilliseconds) { + return EvaluateResult::NewError(); + } + int64_t seconds = value / kMillisecondsPerSecond; + int32_t nanos = (value % kMillisecondsPerSecond) * 1000000LL; + if (nanos < 0) { + seconds--; + nanos += kNanosecondsPerSecond; + } + if (nanos > kTimestampMaxNanos) { + return EvaluateResult::NewError(); + } + google_firestore_v1_Value result; + result.which_value_type = google_firestore_v1_Value_timestamp_value_tag; + result.timestamp_value.seconds = seconds; + result.timestamp_value.nanos = nanos; + return EvaluateResult::NewValue(nanopb::MakeMessage(result)); +} + +EvaluateResult CoreUnixSecondsToTimestamp::ToTimestamp(int64_t value) const { + if (value < kTimestampMinSeconds || value > kTimestampMaxSeconds) { + return EvaluateResult::NewError(); + } + google_firestore_v1_Value result; + result.which_value_type = google_firestore_v1_Value_timestamp_value_tag; + result.timestamp_value.seconds = value; + result.timestamp_value.nanos = 0; + return EvaluateResult::NewValue(nanopb::MakeMessage(result)); +} + +EvaluateResult TimestampToUnixBase::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "Timestamp to Unix conversion requires exactly 1 param"); + EvaluateResult evaluated = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + switch (evaluated.type()) { + case EvaluateResult::ResultType::kTimestamp: { + return ToUnix(evaluated.value()->timestamp_value); + } + case EvaluateResult::ResultType::kNull: + return EvaluateResult::NewNull(); + default: + return EvaluateResult::NewError(); + } +} + +EvaluateResult CoreTimestampToUnixMicros::ToUnix( + const google_protobuf_Timestamp& ts) const { + absl::optional seconds_part = + SafeMultiply(ts.seconds, kMicrosecondsPerSecond); + if (!seconds_part.has_value()) { + return EvaluateResult::NewError(); + } + int64_t micros = seconds_part.value() + ts.nanos / kNanosecondsPerMicrosecond; + return EvaluateResult::NewValue(IntValue(micros)); +} + +EvaluateResult CoreTimestampToUnixMillis::ToUnix( + const google_protobuf_Timestamp& ts) const { + absl::optional seconds_part = + SafeMultiply(ts.seconds, kMillisecondsPerSecond); + if (!seconds_part.has_value()) { + return EvaluateResult::NewError(); + } + int64_t millis = seconds_part.value() + ts.nanos / 1000000LL; + return EvaluateResult::NewValue(IntValue(millis)); +} + +EvaluateResult CoreTimestampToUnixSeconds::ToUnix( + const google_protobuf_Timestamp& ts) const { + if (ts.seconds < kTimestampMinSeconds || ts.seconds > kTimestampMaxSeconds) { + return EvaluateResult::NewError(); + } + return EvaluateResult::NewValue(IntValue(ts.seconds)); +} + +EvaluateResult TimestampArithmeticBase::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 3, + "Timestamp arithmetic requires exactly 3 params"); + + EvaluateResult ts_result = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + EvaluateResult unit_result = + expr_->params()[1]->ToEvaluable()->Evaluate(context, document); + EvaluateResult amount_result = + expr_->params()[2]->ToEvaluable()->Evaluate(context, document); + + if (ts_result.IsErrorOrUnset() || unit_result.IsErrorOrUnset() || + amount_result.IsErrorOrUnset()) { + return EvaluateResult::NewError(); + } + if (ts_result.IsNull() || unit_result.IsNull() || amount_result.IsNull()) { + return EvaluateResult::NewNull(); + } + if (ts_result.type() != EvaluateResult::ResultType::kTimestamp || + unit_result.type() != EvaluateResult::ResultType::kString || + amount_result.type() != EvaluateResult::ResultType::kInt) { + return EvaluateResult::NewError(); + } + + const google_protobuf_Timestamp& ts = ts_result.value()->timestamp_value; + absl::string_view unit = + nanopb::MakeStringView(unit_result.value()->string_value); + int64_t amount = amount_result.value()->integer_value; + + absl::optional micros_to_operate; + if (unit == "microsecond") { + micros_to_operate = amount; + } else if (unit == "millisecond") { + micros_to_operate = SafeMultiply(amount, 1000); + } else if (unit == "second") { + micros_to_operate = SafeMultiply(amount, kMicrosecondsPerSecond); + } else if (unit == "minute") { + micros_to_operate = SafeMultiply(amount, 60 * kMicrosecondsPerSecond); + } else if (unit == "hour") { + micros_to_operate = SafeMultiply(amount, 3600 * kMicrosecondsPerSecond); + } else if (unit == "day") { + micros_to_operate = SafeMultiply(amount, 86400 * kMicrosecondsPerSecond); + } else { + return EvaluateResult::NewError(); + } + + if (!micros_to_operate.has_value()) { + return EvaluateResult::NewError(); + } + + absl::optional seconds_part = + SafeMultiply(ts.seconds, kMicrosecondsPerSecond); + absl::optional initial_micros; + if (seconds_part.has_value()) { + initial_micros = + SafeAdd(seconds_part.value(), ts.nanos / kNanosecondsPerMicrosecond); + } + + if (!initial_micros.has_value()) { + return EvaluateResult::NewError(); + } + + absl::optional final_micros = + PerformArithmetic(initial_micros.value(), micros_to_operate.value()); + if (!final_micros.has_value()) { + return EvaluateResult::NewError(); + } + + return MicrosToTimestampResult(final_micros.value()); +} + +absl::optional CoreTimestampAdd::PerformArithmetic( + int64_t initial_micros, int64_t micros_to_operate) const { + return SafeAdd(initial_micros, micros_to_operate); +} + +absl::optional CoreTimestampSub::PerformArithmetic( + int64_t initial_micros, int64_t micros_to_operate) const { + return SafeSubtract(initial_micros, micros_to_operate); +} + +} // namespace core +} // namespace firestore +} // namespace firebase \ No newline at end of file diff --git a/Firestore/core/src/core/pipeline/evaluation/timestamp.h b/Firestore/core/src/core/pipeline/evaluation/timestamp.h new file mode 100644 index 00000000000..859d63efb22 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/timestamp.h @@ -0,0 +1,157 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TIMESTAMP_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TIMESTAMP_H_ + +#include +#include "Firestore/core/src/core/pipeline/expression.h" + +namespace firebase { +namespace firestore { +namespace core { + +/** Base class for converting Unix time (micros/millis/seconds) to Timestamp. */ +class UnixToTimestampBase : public EvaluableExpr { + public: + explicit UnixToTimestampBase(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + protected: + /** Performs the specific conversion logic after input validation. */ + virtual EvaluateResult ToTimestamp(int64_t value) const = 0; + + std::unique_ptr expr_; +}; + +// Note: Implementations are in expressions_eval.cc +class CoreUnixMicrosToTimestamp : public UnixToTimestampBase { + public: + explicit CoreUnixMicrosToTimestamp(const api::FunctionExpr& expr); + + protected: + EvaluateResult ToTimestamp(int64_t value) const override; +}; + +class CoreUnixMillisToTimestamp : public UnixToTimestampBase { + public: + explicit CoreUnixMillisToTimestamp(const api::FunctionExpr& expr); + + protected: + EvaluateResult ToTimestamp(int64_t value) const override; +}; + +class CoreUnixSecondsToTimestamp : public UnixToTimestampBase { + public: + explicit CoreUnixSecondsToTimestamp(const api::FunctionExpr& expr); + + protected: + EvaluateResult ToTimestamp(int64_t value) const override; +}; + +/** Base class for converting Timestamp to Unix time (micros/millis/seconds). */ +class TimestampToUnixBase : public EvaluableExpr { + public: + explicit TimestampToUnixBase(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + protected: + /** Performs the specific conversion logic after input validation. */ + virtual EvaluateResult ToUnix( + const google_protobuf_Timestamp& ts) const = 0; // Use protobuf type + + std::unique_ptr expr_; +}; + +// Note: Implementations are in expressions_eval.cc +class CoreTimestampToUnixMicros : public TimestampToUnixBase { + public: + explicit CoreTimestampToUnixMicros(const api::FunctionExpr& expr); + + protected: + EvaluateResult ToUnix(const google_protobuf_Timestamp& ts) const override; +}; + +class CoreTimestampToUnixMillis : public TimestampToUnixBase { + public: + explicit CoreTimestampToUnixMillis(const api::FunctionExpr& expr); + + protected: + EvaluateResult ToUnix(const google_protobuf_Timestamp& ts) const override; +}; + +class CoreTimestampToUnixSeconds : public TimestampToUnixBase { + public: + explicit CoreTimestampToUnixSeconds(const api::FunctionExpr& expr); + + protected: + EvaluateResult ToUnix(const google_protobuf_Timestamp& ts) const override; +}; + +/** Base class for timestamp arithmetic (add/sub). */ +class TimestampArithmeticBase : public EvaluableExpr { + public: + explicit TimestampArithmeticBase(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + protected: + /** Performs the specific arithmetic operation. */ + // Return optional as int128 is not needed and adds complexity + virtual absl::optional PerformArithmetic( + int64_t initial_micros, int64_t micros_to_operate) const = 0; + + std::unique_ptr expr_; +}; + +// Note: Implementations are in expressions_eval.cc +class CoreTimestampAdd : public TimestampArithmeticBase { + public: + explicit CoreTimestampAdd(const api::FunctionExpr& expr); + + protected: + absl::optional PerformArithmetic( + int64_t initial_micros, int64_t micros_to_operate) const override; +}; + +class CoreTimestampSub : public TimestampArithmeticBase { + public: + explicit CoreTimestampSub(const api::FunctionExpr& expr); + + protected: + absl::optional PerformArithmetic( + int64_t initial_micros, int64_t micros_to_operate) const override; +}; + +} // namespace core +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TIMESTAMP_H_ diff --git a/Firestore/core/src/core/pipeline/evaluation/type.cc b/Firestore/core/src/core/pipeline/evaluation/type.cc new file mode 100644 index 00000000000..9782ea457b1 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/type.cc @@ -0,0 +1,136 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/core/pipeline/evaluation/type.h" +#include "Firestore/core/src/core/pipeline/evaluation/logical.h" +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/util/hard_assert.h" + +namespace firebase { +namespace firestore { +namespace core { + +EvaluateResult CoreIsNan::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "is_nan() function requires exactly 1 param"); + + EvaluateResult evaluated = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + switch (evaluated.type()) { + case EvaluateResult::ResultType::kInt: + // Integers are never NaN + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + case EvaluateResult::ResultType::kDouble: + // Check if the double value is NaN + return EvaluateResult::NewValue(nanopb::MakeMessage( + model::IsNaNValue(*evaluated.value()) ? model::TrueValue() + : model::FalseValue())); + case EvaluateResult::ResultType::kNull: + // is_nan(null) -> null + return EvaluateResult::NewNull(); + default: + // is_nan applied to non-numeric, non-null is an error + return EvaluateResult::NewError(); + } +} + +EvaluateResult CoreIsNotNan::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "is_not_nan() function requires exactly 1 param"); + + CoreNot equivalent(api::FunctionExpr( + "not", {std::make_shared("is_nan", expr_->params())})); + return equivalent.Evaluate(context, document); +} + +EvaluateResult CoreIsNull::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "is_null() function requires exactly 1 param"); + + EvaluateResult evaluated = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + switch (evaluated.type()) { + case EvaluateResult::ResultType::kNull: + return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); + case EvaluateResult::ResultType::kUnset: + case EvaluateResult::ResultType::kError: + // is_null on error/unset is an error + return EvaluateResult::NewError(); + default: + // is_null on any other value is false + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } +} + +EvaluateResult CoreIsNotNull::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "is_not_null() function requires exactly 1 param"); + + CoreNot equivalent(api::FunctionExpr( + "not", + {std::make_shared("is_null", expr_->params())})); + return equivalent.Evaluate(context, document); +} + +EvaluateResult CoreIsError::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "is_error() function requires exactly 1 param"); + + EvaluateResult evaluated = + expr_->params()[0]->ToEvaluable()->Evaluate(context, document); + switch (evaluated.type()) { + case EvaluateResult::ResultType::kError: + return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); + default: + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + } +} + +EvaluateResult CoreExists::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const { + HARD_ASSERT(expr_->params().size() == 1, + "exists() function requires exactly 1 param"); + + std::unique_ptr operand_evaluable = + expr_->params()[0]->ToEvaluable(); + EvaluateResult evaluated = operand_evaluable->Evaluate(context, document); + + switch (evaluated.type()) { + case EvaluateResult::ResultType::kError: + return EvaluateResult::NewError(); // Propagate error + case EvaluateResult::ResultType::kUnset: + // Unset field means it doesn't exist + return EvaluateResult::NewValue(nanopb::MakeMessage(model::FalseValue())); + default: + // Null or any other value means it exists + return EvaluateResult::NewValue(nanopb::MakeMessage(model::TrueValue())); + } +} + +} // namespace core +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/core/pipeline/evaluation/type.h b/Firestore/core/src/core/pipeline/evaluation/type.h new file mode 100644 index 00000000000..e5928ba7468 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/type.h @@ -0,0 +1,109 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TYPE_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TYPE_H_ + +#include +#include "Firestore/core/src/core/pipeline/expression.h" + +namespace firebase { +namespace firestore { +namespace core { + +class CoreIsNan : public EvaluableExpr { + public: + explicit CoreIsNan(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreIsNotNan : public EvaluableExpr { + public: + explicit CoreIsNotNan(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreIsNull : public EvaluableExpr { + public: + explicit CoreIsNull(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreIsNotNull : public EvaluableExpr { + public: + explicit CoreIsNotNull(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreIsError : public EvaluableExpr { + public: + explicit CoreIsError(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreExists : public EvaluableExpr { + public: + explicit CoreExists(const api::FunctionExpr& expr) + : expr_(std::make_unique(expr)) { + } + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +} // namespace core +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TYPE_H_ diff --git a/Firestore/core/src/core/pipeline/evaluation/util.cc b/Firestore/core/src/core/pipeline/evaluation/util.cc new file mode 100644 index 00000000000..ac9aa45848e --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/util.cc @@ -0,0 +1,105 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/core/pipeline/evaluation/util.h" + +#include +#include + +namespace firebase { +namespace firestore { +namespace core { + +nanopb::Message IntValue(int64_t val) { + google_firestore_v1_Value proto; + proto.which_value_type = google_firestore_v1_Value_integer_value_tag; + proto.integer_value = val; + return nanopb::MakeMessage(std::move(proto)); +} + +absl::optional SafeAdd(int64_t lhs, int64_t rhs) { + int64_t result; +#if defined(__clang__) || defined(__GNUC__) + if (__builtin_add_overflow(lhs, rhs, &result)) { + return absl::nullopt; + } +#else + if ((rhs > 0 && lhs > std::numeric_limits::max() - rhs) || + (rhs < 0 && lhs < std::numeric_limits::min() - rhs)) { + return absl::nullopt; + } + result = lhs + rhs; +#endif + return result; +} + +absl::optional SafeSubtract(int64_t lhs, int64_t rhs) { + int64_t result; +#if defined(__clang__) || defined(__GNUC__) + if (__builtin_sub_overflow(lhs, rhs, &result)) { + return absl::nullopt; + } +#else + if ((rhs < 0 && lhs > std::numeric_limits::max() + rhs) || + (rhs > 0 && lhs < std::numeric_limits::min() + rhs)) { + return absl::nullopt; + } + result = lhs - rhs; +#endif + return result; +} + +absl::optional SafeMultiply(int64_t lhs, int64_t rhs) { + int64_t result; +#if defined(__clang__) || defined(__GNUC__) + if (__builtin_mul_overflow(lhs, rhs, &result)) { + return absl::nullopt; + } +#else + if (lhs != 0 && rhs != 0) { + if (lhs > std::numeric_limits::max() / rhs || + lhs < std::numeric_limits::min() / rhs) { + return absl::nullopt; + } + } + result = lhs * rhs; +#endif + return result; +} + +absl::optional SafeDivide(int64_t lhs, int64_t rhs) { + if (rhs == 0) { + return absl::nullopt; + } + if (lhs == std::numeric_limits::min() && rhs == -1) { + return absl::nullopt; + } + return lhs / rhs; +} + +absl::optional SafeMod(int64_t lhs, int64_t rhs) { + if (rhs == 0) { + return absl::nullopt; + } + if (lhs == std::numeric_limits::min() && rhs == -1) { + return absl::nullopt; + } + return lhs % rhs; +} + +} // namespace core +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/core/pipeline/evaluation/util.h b/Firestore/core/src/core/pipeline/evaluation/util.h new file mode 100644 index 00000000000..bb2cd6cdeb7 --- /dev/null +++ b/Firestore/core/src/core/pipeline/evaluation/util.h @@ -0,0 +1,40 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_UTIL_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_UTIL_H_ + +#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" +#include "Firestore/core/src/nanopb/message.h" +#include "absl/types/optional.h" + +namespace firebase { +namespace firestore { +namespace core { + +nanopb::Message IntValue(int64_t val); + +absl::optional SafeAdd(int64_t lhs, int64_t rhs); +absl::optional SafeSubtract(int64_t lhs, int64_t rhs); +absl::optional SafeMultiply(int64_t lhs, int64_t rhs); +absl::optional SafeDivide(int64_t lhs, int64_t rhs); +absl::optional SafeMod(int64_t lhs, int64_t rhs); + +} // namespace core +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_UTIL_H_ diff --git a/Firestore/core/src/core/pipeline/expression.cc b/Firestore/core/src/core/pipeline/expression.cc new file mode 100644 index 00000000000..e3085a57ab7 --- /dev/null +++ b/Firestore/core/src/core/pipeline/expression.cc @@ -0,0 +1,279 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/core/pipeline/expression.h" + +#include +#include // For std::move + +#include "Firestore/core/src/core/pipeline/aggregates.h" +#include "Firestore/core/src/core/pipeline/evaluation/arithmetic.h" +#include "Firestore/core/src/core/pipeline/evaluation/array.h" +#include "Firestore/core/src/core/pipeline/evaluation/comparison.h" +#include "Firestore/core/src/core/pipeline/evaluation/logical.h" +#include "Firestore/core/src/core/pipeline/evaluation/map.h" +#include "Firestore/core/src/core/pipeline/evaluation/string.h" +#include "Firestore/core/src/core/pipeline/evaluation/timestamp.h" +#include "Firestore/core/src/core/pipeline/evaluation/type.h" +#include "Firestore/core/src/model/mutable_document.h" +#include "Firestore/core/src/model/server_timestamp_util.h" +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/nanopb/message.h" +#include "Firestore/core/src/remote/serializer.h" +#include "Firestore/core/src/util/hard_assert.h" + +namespace firebase { +namespace firestore { +namespace core { + +EvaluateResult::EvaluateResult( + EvaluateResult::ResultType type, + nanopb::Message message) + : value_(std::move(message)), type_(type) { +} + +EvaluateResult EvaluateResult::NewNull() { + return EvaluateResult( + ResultType::kNull, + nanopb::Message(model::NullValue())); +} + +EvaluateResult EvaluateResult::NewValue( + nanopb::Message value) { + if (model::IsNullValue(*value)) { + return EvaluateResult::NewNull(); + } else if (value->which_value_type == + google_firestore_v1_Value_boolean_value_tag) { + return EvaluateResult(ResultType::kBoolean, std::move(value)); + } else if (model::IsInteger(*value)) { + return EvaluateResult(ResultType::kInt, std::move(value)); + } else if (model::IsDouble(*value)) { + return EvaluateResult(ResultType::kDouble, std::move(value)); + } else if (value->which_value_type == + google_firestore_v1_Value_timestamp_value_tag) { + return EvaluateResult(ResultType::kTimestamp, std::move(value)); + } else if (value->which_value_type == + google_firestore_v1_Value_string_value_tag) { + return EvaluateResult(ResultType::kString, std::move(value)); + } else if (value->which_value_type == + google_firestore_v1_Value_bytes_value_tag) { + return EvaluateResult(ResultType::kBytes, std::move(value)); + } else if (value->which_value_type == + google_firestore_v1_Value_reference_value_tag) { + return EvaluateResult(ResultType::kReference, std::move(value)); + } else if (value->which_value_type == + google_firestore_v1_Value_geo_point_value_tag) { + return EvaluateResult(ResultType::kGeoPoint, std::move(value)); + } else if (model::IsArray(*value)) { + return EvaluateResult(ResultType::kArray, std::move(value)); + } else if (model::IsVectorValue(*value)) { + // vector value must be before map value + return EvaluateResult(ResultType::kVector, std::move(value)); + } else if (model::IsMap(*value)) { + return EvaluateResult(ResultType::kMap, std::move(value)); + } else { + return EvaluateResult(ResultType::kError, {}); + } +} + +namespace { + +nanopb::Message GetServerTimestampValue( + const api::EvaluateContext& context, + const google_firestore_v1_Value& timestamp_sentinel) { + if (context.listen_options().server_timestamp_behavior() == + ListenOptions::ServerTimestampBehavior::kEstimate) { + google_firestore_v1_Value result; + result.which_value_type = google_firestore_v1_Value_timestamp_value_tag; + result.timestamp_value = model::GetLocalWriteTime(timestamp_sentinel); + return nanopb::MakeMessage(result); + } + + if (context.listen_options().server_timestamp_behavior() == + ListenOptions::ServerTimestampBehavior::kPrevious) { + auto result = model::GetPreviousValue(timestamp_sentinel); + if (result.has_value()) { + return model::DeepClone(result.value()); + } + } + + return nanopb::MakeMessage(model::NullValue()); +} + +} // namespace + +EvaluateResult CoreField::Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& input) const { + auto* field = dynamic_cast(expr_.get()); + if (field->alias() == model::FieldPath::kDocumentKeyPath) { + google_firestore_v1_Value result; + + result.which_value_type = google_firestore_v1_Value_reference_value_tag; + result.reference_value = context.serializer().EncodeKey(input.key()); + + return EvaluateResult::NewValue(nanopb::MakeMessage(std::move(result))); + } + + if (field->alias() == model::FieldPath::kUpdateTimePath) { + google_firestore_v1_Value result; + + result.which_value_type = google_firestore_v1_Value_timestamp_value_tag; + result.timestamp_value = + context.serializer().EncodeVersion(input.version()); + + return EvaluateResult::NewValue(nanopb::MakeMessage(std::move(result))); + } + + // TODO(pipeline): Add create time support. + + // Return 'UNSET' if the field doesn't exist, otherwise the Value. + const auto& result = input.field(field->field_path()); + if (result.has_value()) { + if (model::IsServerTimestamp(result.value())) { + return EvaluateResult::NewValue( + GetServerTimestampValue(context, result.value())); + } + + // DeepClone the field value to avoid modifying the original. + return EvaluateResult::NewValue(model::DeepClone(result.value())); + } else { + return EvaluateResult::NewUnset(); + } +} + +EvaluateResult CoreConstant::Evaluate(const api::EvaluateContext&, + const model::PipelineInputOutput&) const { + auto* constant = dynamic_cast(expr_.get()); + return EvaluateResult::NewValue(nanopb::MakeMessage(constant->to_proto())); +} + +std::unique_ptr FunctionToEvaluable( + const api::FunctionExpr& function) { + if (function.name() == "equal") { + return std::make_unique(function); + } else if (function.name() == "add") { + return std::make_unique(function); + } else if (function.name() == "subtract") { + return std::make_unique(function); + } else if (function.name() == "multiply") { + return std::make_unique(function); + } else if (function.name() == "divide") { + return std::make_unique(function); + } else if (function.name() == "mod") { + return std::make_unique(function); + } else if (function.name() == "not_equal") { + return std::make_unique(function); + } else if (function.name() == "less_than") { + return std::make_unique(function); + } else if (function.name() == "less_than_or_equal") { + return std::make_unique(function); + } else if (function.name() == "greater_than") { + return std::make_unique(function); + } else if (function.name() == "greater_than_or_equal") { + return std::make_unique(function); + } else if (function.name() == "array_reverse") { + return std::make_unique(function); + } else if (function.name() == "array_contains") { + return std::make_unique(function); + } else if (function.name() == "array_contains_all") { + return std::make_unique(function); + } else if (function.name() == "array_contains_any") { + return std::make_unique(function); + } else if (function.name() == "array_length") { + return std::make_unique(function); + } else if (function.name() == "exists") { + return std::make_unique(function); + } else if (function.name() == "not") { + return std::make_unique(function); + } else if (function.name() == "and") { + return std::make_unique(function); + } else if (function.name() == "or") { + return std::make_unique(function); + } else if (function.name() == "xor") { + return std::make_unique(function); + } else if (function.name() == "cond") { + return std::make_unique(function); + } else if (function.name() == "equal_any") { + return std::make_unique(function); + } else if (function.name() == "not_equal_any") { + return std::make_unique(function); + } else if (function.name() == "is_nan") { + return std::make_unique(function); + } else if (function.name() == "is_not_nan") { + return std::make_unique(function); + } else if (function.name() == "is_null") { + return std::make_unique(function); + } else if (function.name() == "is_not_null") { + return std::make_unique(function); + } else if (function.name() == "is_error") { + return std::make_unique(function); + } else if (function.name() == "maximum") { + return std::make_unique(function); + } else if (function.name() == "minimum") { + return std::make_unique(function); + } else if (function.name() == "map_get") { + return std::make_unique(function); + } else if (function.name() == "byte_length") { + return std::make_unique(function); + } else if (function.name() == "char_length") { + return std::make_unique(function); + } else if (function.name() == "string_concat") { + return std::make_unique(function); + } else if (function.name() == "ends_with") { + return std::make_unique(function); + } else if (function.name() == "starts_with") { + return std::make_unique(function); + } else if (function.name() == "string_contains") { + return std::make_unique(function); + } else if (function.name() == "to_lower") { + return std::make_unique(function); + } else if (function.name() == "to_upper") { + return std::make_unique(function); + } else if (function.name() == "trim") { + return std::make_unique(function); + } else if (function.name() == "string_reverse") { + return std::make_unique(function); + } else if (function.name() == "regex_contains") { + return std::make_unique(function); + } else if (function.name() == "regex_match") { + return std::make_unique(function); + } else if (function.name() == "like") { + return std::make_unique(function); + } else if (function.name() == "unix_micros_to_timestamp") { + return std::make_unique(function); + } else if (function.name() == "unix_millis_to_timestamp") { + return std::make_unique(function); + } else if (function.name() == "unix_seconds_to_timestamp") { + return std::make_unique(function); + } else if (function.name() == "timestamp_to_unix_micros") { + return std::make_unique(function); + } else if (function.name() == "timestamp_to_unix_millis") { + return std::make_unique(function); + } else if (function.name() == "timestamp_to_unix_seconds") { + return std::make_unique(function); + } else if (function.name() == "timestamp_add") { + return std::make_unique(function); + } else if (function.name() == "timestamp_sub") { + return std::make_unique(function); + } + + HARD_FAIL("Unsupported function name: %s", function.name()); +} + +} // namespace core +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/core/pipeline/expression.h b/Firestore/core/src/core/pipeline/expression.h new file mode 100644 index 00000000000..759d33b3876 --- /dev/null +++ b/Firestore/core/src/core/pipeline/expression.h @@ -0,0 +1,155 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_H_ + +#include +#include +#include +#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" + +#include "Firestore/core/src/api/expressions.h" +#include "Firestore/core/src/api/stages.h" +#include "Firestore/core/src/nanopb/message.h" +#include "absl/types/optional.h" + +namespace firebase { +namespace firestore { +namespace core { + +// Forward declaration +class EvaluableExpr; + +/** Represents the result of evaluating an expression. */ +class EvaluateResult { + public: + // TODO(BSON): Add bson types here when integrating. + enum class ResultType { + kError = 0, + kUnset = 1, + kNull = 2, + kBoolean = 3, + kInt = 4, + kDouble = 5, + kTimestamp = 6, + kString = 7, + kBytes = 8, + kReference = 9, + kGeoPoint = 10, + kArray = 11, + kMap = 12, + kFieldReference = 13, + kVector = 14 + }; + + // Disallow default instance as it is invalid + EvaluateResult() = delete; + + static EvaluateResult NewError() { + return EvaluateResult(ResultType::kError, + nanopb::Message()); + } + + static EvaluateResult NewUnset() { + return EvaluateResult(ResultType::kUnset, + nanopb::Message()); + } + + static EvaluateResult NewNull(); + + static EvaluateResult NewValue( + nanopb::Message value); + + ResultType type() const { + return type_; + } + + const google_firestore_v1_Value* value() const { + return value_.get(); + } + + bool IsErrorOrUnset() const { + return type_ == ResultType::kError || type_ == ResultType::kUnset; + } + + bool IsNull() const { + return type_ == ResultType::kNull; + } + + private: + EvaluateResult(ResultType type, + nanopb::Message message); + + nanopb::Message value_; + ResultType type_; +}; + +/** An interface representing an expression that can be evaluated. */ +class EvaluableExpr { + public: + virtual ~EvaluableExpr() = default; + + /** + * Evaluates the expression against the given document within the provided + * context. + * @param context The context for evaluation (e.g., variable bindings). + * @param document The document to evaluate against. + * @return The result of the evaluation. + */ + virtual EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const = 0; +}; + +class CoreField : public EvaluableExpr { + public: + explicit CoreField(std::unique_ptr expr) : expr_(std::move(expr)) { + } + + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +class CoreConstant : public EvaluableExpr { + public: + explicit CoreConstant(std::unique_ptr expr) + : expr_(std::move(expr)) { + } + + EvaluateResult Evaluate( + const api::EvaluateContext& context, + const model::PipelineInputOutput& document) const override; + + private: + std::unique_ptr expr_; +}; + +/** + * Converts a high-level expression representation into an evaluable one. + */ +std::unique_ptr FunctionToEvaluable( + const api::FunctionExpr& function); + +} // namespace core +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_H_ From 78bb8a60cd3be97718dabd4cdbf71c688965649e Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Mon, 1 Dec 2025 12:07:29 -0500 Subject: [PATCH 29/36] fix format --- Firestore/core/src/core/pipeline/evaluation/arithmetic.cc | 3 ++- Firestore/core/src/core/pipeline/evaluation/array.cc | 2 +- Firestore/core/src/core/pipeline/evaluation/string.cc | 2 +- Firestore/core/src/core/pipeline/evaluation/timestamp.cc | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Firestore/core/src/core/pipeline/evaluation/arithmetic.cc b/Firestore/core/src/core/pipeline/evaluation/arithmetic.cc index 6acc7b9cb27..9f3c4e0641e 100644 --- a/Firestore/core/src/core/pipeline/evaluation/arithmetic.cc +++ b/Firestore/core/src/core/pipeline/evaluation/arithmetic.cc @@ -15,11 +15,12 @@ */ #include "Firestore/core/src/core/pipeline/evaluation/arithmetic.h" -#include "Firestore/core/src/core/pipeline/evaluation/util.h" #include #include +#include +#include "Firestore/core/src/core/pipeline/evaluation/util.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/util/hard_assert.h" #include "absl/types/optional.h" diff --git a/Firestore/core/src/core/pipeline/evaluation/array.cc b/Firestore/core/src/core/pipeline/evaluation/array.cc index dd646ea0b77..96ec187e5e2 100644 --- a/Firestore/core/src/core/pipeline/evaluation/array.cc +++ b/Firestore/core/src/core/pipeline/evaluation/array.cc @@ -15,7 +15,6 @@ */ #include "Firestore/core/src/core/pipeline/evaluation/array.h" -#include "Firestore/core/src/core/pipeline/evaluation/util.h" #include #include @@ -23,6 +22,7 @@ #include #include "Firestore/core/src/core/pipeline/evaluation/logical.h" +#include "Firestore/core/src/core/pipeline/evaluation/util.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/util/hard_assert.h" diff --git a/Firestore/core/src/core/pipeline/evaluation/string.cc b/Firestore/core/src/core/pipeline/evaluation/string.cc index d993980f566..65db0b58d8c 100644 --- a/Firestore/core/src/core/pipeline/evaluation/string.cc +++ b/Firestore/core/src/core/pipeline/evaluation/string.cc @@ -15,7 +15,6 @@ */ #include "Firestore/core/src/core/pipeline/evaluation/string.h" -#include "Firestore/core/src/core/pipeline/evaluation/util.h" #include #include @@ -24,6 +23,7 @@ #include #include +#include "Firestore/core/src/core/pipeline/evaluation/util.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/util/hard_assert.h" #include "absl/strings/match.h" diff --git a/Firestore/core/src/core/pipeline/evaluation/timestamp.cc b/Firestore/core/src/core/pipeline/evaluation/timestamp.cc index e30815c5f68..2748a3b057d 100644 --- a/Firestore/core/src/core/pipeline/evaluation/timestamp.cc +++ b/Firestore/core/src/core/pipeline/evaluation/timestamp.cc @@ -300,4 +300,4 @@ absl::optional CoreTimestampSub::PerformArithmetic( } // namespace core } // namespace firestore -} // namespace firebase \ No newline at end of file +} // namespace firebase From 28ed0d3ff78abf4b6ecbf938ce550c9d9336ea17 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Mon, 1 Dec 2025 13:21:34 -0500 Subject: [PATCH 30/36] optimize the file dependency --- Firestore/core/src/api/expressions.cc | 2 +- Firestore/core/src/api/stages.cc | 5 +-- Firestore/core/src/core/expressions_eval.h | 31 ------------------- Firestore/core/src/core/pipeline_util.cc | 10 +----- .../unit/core/expressions/arithmetic_test.cc | 6 +--- .../test/unit/core/expressions/array_test.cc | 13 +++----- .../unit/core/expressions/comparison_test.cc | 13 ++++---- .../test/unit/core/expressions/debug_test.cc | 13 +++----- .../test/unit/core/expressions/field_test.cc | 10 +++--- .../unit/core/expressions/logical_test.cc | 3 +- .../test/unit/core/expressions/map_test.cc | 10 +++--- .../expressions/mirroring_semantics_test.cc | 13 ++++---- .../test/unit/core/expressions/string_test.cc | 4 +-- .../test/unit/testutil/expression_test_util.h | 29 +++++++++++------ 14 files changed, 55 insertions(+), 107 deletions(-) delete mode 100644 Firestore/core/src/core/expressions_eval.h diff --git a/Firestore/core/src/api/expressions.cc b/Firestore/core/src/api/expressions.cc index 495314624a5..1ec99c287b1 100644 --- a/Firestore/core/src/api/expressions.cc +++ b/Firestore/core/src/api/expressions.cc @@ -19,7 +19,7 @@ #include #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" -#include "Firestore/core/src/core/expressions_eval.h" +#include "Firestore/core/src/core/pipeline/expression.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/nanopb/nanopb_util.h" diff --git a/Firestore/core/src/api/stages.cc b/Firestore/core/src/api/stages.cc index 7b24604e23a..1a33958b8cb 100644 --- a/Firestore/core/src/api/stages.cc +++ b/Firestore/core/src/api/stages.cc @@ -20,19 +20,16 @@ #include #include #include -#include #include #include #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" #include "Firestore/core/src/api/pipeline.h" -#include "Firestore/core/src/core/expressions_eval.h" -#include "Firestore/core/src/model/document.h" +#include "Firestore/core/src/core/pipeline/expression.h" #include "Firestore/core/src/model/document_key.h" #include "Firestore/core/src/model/mutable_document.h" #include "Firestore/core/src/model/resource_path.h" #include "Firestore/core/src/model/value_util.h" -#include "Firestore/core/src/nanopb/message.h" #include "Firestore/core/src/nanopb/nanopb_util.h" #include "Firestore/core/src/util/comparison.h" #include "Firestore/core/src/util/hard_assert.h" diff --git a/Firestore/core/src/core/expressions_eval.h b/Firestore/core/src/core/expressions_eval.h deleted file mode 100644 index fbf2c197c7d..00000000000 --- a/Firestore/core/src/core/expressions_eval.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIRESTORE_CORE_SRC_CORE_EXPRESSIONS_EVAL_H_ -#define FIRESTORE_CORE_SRC_CORE_EXPRESSIONS_EVAL_H_ - -#include "Firestore/core/src/core/pipeline/aggregates.h" -#include "Firestore/core/src/core/pipeline/evaluation/arithmetic.h" -#include "Firestore/core/src/core/pipeline/evaluation/array.h" -#include "Firestore/core/src/core/pipeline/evaluation/comparison.h" -#include "Firestore/core/src/core/pipeline/evaluation/logical.h" -#include "Firestore/core/src/core/pipeline/evaluation/map.h" -#include "Firestore/core/src/core/pipeline/evaluation/string.h" -#include "Firestore/core/src/core/pipeline/evaluation/timestamp.h" -#include "Firestore/core/src/core/pipeline/evaluation/type.h" -#include "Firestore/core/src/core/pipeline/expression.h" - -#endif // FIRESTORE_CORE_SRC_CORE_EXPRESSIONS_EVAL_H_ diff --git a/Firestore/core/src/core/pipeline_util.cc b/Firestore/core/src/core/pipeline_util.cc index 212a801f1bc..9ed35af614d 100644 --- a/Firestore/core/src/core/pipeline_util.cc +++ b/Firestore/core/src/core/pipeline_util.cc @@ -17,7 +17,6 @@ #include "Firestore/core/src/core/pipeline_util.h" #include -#include #include #include #include @@ -27,17 +26,11 @@ #include "Firestore/core/src/api/realtime_pipeline.h" #include "Firestore/core/src/api/stages.h" #include "Firestore/core/src/core/bound.h" -#include "Firestore/core/src/core/expressions_eval.h" -#include "Firestore/core/src/core/filter.h" -#include "Firestore/core/src/core/order_by.h" +#include "Firestore/core/src/core/pipeline/expression.h" #include "Firestore/core/src/core/pipeline_run.h" #include "Firestore/core/src/core/query.h" -#include "Firestore/core/src/model/document.h" #include "Firestore/core/src/model/document_set.h" -#include "Firestore/core/src/model/field_path.h" -#include "Firestore/core/src/model/mutable_document.h" #include "Firestore/core/src/model/value_util.h" -#include "Firestore/core/src/remote/serializer.h" #include "Firestore/core/src/util/comparison.h" #include "Firestore/core/src/util/exception.h" #include "Firestore/core/src/util/hard_assert.h" @@ -46,7 +39,6 @@ #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" #include "absl/types/optional.h" -#include "absl/types/variant.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/test/unit/core/expressions/arithmetic_test.cc b/Firestore/core/test/unit/core/expressions/arithmetic_test.cc index 9e9d6c8f606..af825cc3eb3 100644 --- a/Firestore/core/test/unit/core/expressions/arithmetic_test.cc +++ b/Firestore/core/test/unit/core/expressions/arithmetic_test.cc @@ -14,14 +14,10 @@ * limitations under the License. */ -#include #include #include -#include -#include -#include -#include "Firestore/core/src/core/expressions_eval.h" +#include "Firestore/core/src/core/pipeline/expression.h" #include "Firestore/core/test/unit/testutil/expression_test_util.h" #include "Firestore/core/test/unit/testutil/testutil.h" #include "gmock/gmock.h" diff --git a/Firestore/core/test/unit/core/expressions/array_test.cc b/Firestore/core/test/unit/core/expressions/array_test.cc index 80e6e1ee892..48ce928852a 100644 --- a/Firestore/core/test/unit/core/expressions/array_test.cc +++ b/Firestore/core/test/unit/core/expressions/array_test.cc @@ -19,14 +19,11 @@ #include #include -#include "Firestore/core/src/api/expressions.h" // For api::Expr, api::Constant, api::Field -#include "Firestore/core/src/core/expressions_eval.h" -// #include "Firestore/core/src/model/field_value.h" // Removed incorrect -// include -#include "Firestore/core/src/model/value_util.h" // For value constants like NullValue, NaNValue -#include "Firestore/core/test/unit/testutil/expression_test_util.h" // For test helpers -#include "Firestore/core/test/unit/testutil/testutil.h" // For test helpers like Value, Array, Map -#include "gmock/gmock.h" // For matchers like Returns +#include "Firestore/core/src/api/expressions.h" +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/test/unit/testutil/expression_test_util.h" +#include "Firestore/core/test/unit/testutil/testutil.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" namespace firebase { diff --git a/Firestore/core/test/unit/core/expressions/comparison_test.cc b/Firestore/core/test/unit/core/expressions/comparison_test.cc index 141b803941c..af9d8025fb3 100644 --- a/Firestore/core/test/unit/core/expressions/comparison_test.cc +++ b/Firestore/core/test/unit/core/expressions/comparison_test.cc @@ -21,13 +21,12 @@ #include #include -#include "Firestore/core/src/api/expressions.h" // Include for api::Constant, api::Field -#include "Firestore/core/src/core/expressions_eval.h" // For EvaluateResult, CoreEq etc. -#include "Firestore/core/src/model/database_id.h" // For DatabaseId -#include "Firestore/core/src/model/document_key.h" // For DocumentKey -#include "Firestore/core/src/model/value_util.h" // For value constants like NaNValue, TypeOrder, NullValue, CanonicalId, Equals -#include "Firestore/core/test/unit/testutil/expression_test_util.h" // For EvaluateExpr, EqualExpr, ComparisonValueTestData, RefConstant etc. -#include "Firestore/core/test/unit/testutil/testutil.h" // For test helpers like Value, Array, Map, BlobValue, Doc +#include "Firestore/core/src/api/expressions.h" +#include "Firestore/core/src/model/database_id.h" +#include "Firestore/core/src/model/document_key.h" +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/test/unit/testutil/expression_test_util.h" +#include "Firestore/core/test/unit/testutil/testutil.h" #include "gmock/gmock.h" #include "gtest/gtest.h" diff --git a/Firestore/core/test/unit/core/expressions/debug_test.cc b/Firestore/core/test/unit/core/expressions/debug_test.cc index ae527a16573..ca51bfb8b61 100644 --- a/Firestore/core/test/unit/core/expressions/debug_test.cc +++ b/Firestore/core/test/unit/core/expressions/debug_test.cc @@ -19,14 +19,11 @@ #include #include -#include "Firestore/core/src/api/expressions.h" // For api::Expr, api::IsError -#include "Firestore/core/src/core/expressions_eval.h" -// #include "Firestore/core/src/model/field_value.h" // Not needed, -// True/FalseValue are in value_util.h -#include "Firestore/core/src/model/value_util.h" // For value constants like NullValue, TrueValue, FalseValue -#include "Firestore/core/test/unit/testutil/expression_test_util.h" // For test helpers -#include "Firestore/core/test/unit/testutil/testutil.h" // For test helpers like Value, Array, Map -#include "gmock/gmock.h" // For matchers like Returns +#include "Firestore/core/src/api/expressions.h" +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/test/unit/testutil/expression_test_util.h" +#include "Firestore/core/test/unit/testutil/testutil.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" namespace firebase { diff --git a/Firestore/core/test/unit/core/expressions/field_test.cc b/Firestore/core/test/unit/core/expressions/field_test.cc index 6d134be7b5a..cadead53d72 100644 --- a/Firestore/core/test/unit/core/expressions/field_test.cc +++ b/Firestore/core/test/unit/core/expressions/field_test.cc @@ -16,12 +16,10 @@ #include -#include "Firestore/core/src/api/expressions.h" // For api::Expr -#include "Firestore/core/src/core/expressions_eval.h" -#include "Firestore/core/src/model/value_util.h" // For value constants -#include "Firestore/core/test/unit/testutil/expression_test_util.h" // For test helpers -#include "Firestore/core/test/unit/testutil/testutil.h" // For test helpers like Value, Map, Doc -#include "gmock/gmock.h" // For matchers like Returns +#include "Firestore/core/src/api/expressions.h" +#include "Firestore/core/test/unit/testutil/expression_test_util.h" +#include "Firestore/core/test/unit/testutil/testutil.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" namespace firebase { diff --git a/Firestore/core/test/unit/core/expressions/logical_test.cc b/Firestore/core/test/unit/core/expressions/logical_test.cc index 73f3d10c4d9..365cf607647 100644 --- a/Firestore/core/test/unit/core/expressions/logical_test.cc +++ b/Firestore/core/test/unit/core/expressions/logical_test.cc @@ -22,9 +22,8 @@ #include #include "Firestore/core/src/api/expressions.h" -#include "Firestore/core/src/core/expressions_eval.h" #include "Firestore/core/src/model/field_path.h" -#include "Firestore/core/src/model/value_util.h" // For TrueValue, FalseValue, NullValue +#include "Firestore/core/src/model/value_util.h" #include "Firestore/core/test/unit/testutil/expression_test_util.h" #include "Firestore/core/test/unit/testutil/testutil.h" #include "gmock/gmock.h" diff --git a/Firestore/core/test/unit/core/expressions/map_test.cc b/Firestore/core/test/unit/core/expressions/map_test.cc index 5dc03e738c2..d8da412b8b6 100644 --- a/Firestore/core/test/unit/core/expressions/map_test.cc +++ b/Firestore/core/test/unit/core/expressions/map_test.cc @@ -17,12 +17,10 @@ #include #include -#include "Firestore/core/src/api/expressions.h" // For api::Expr, api::MapGet -#include "Firestore/core/src/core/expressions_eval.h" -#include "Firestore/core/src/model/value_util.h" // For value constants -#include "Firestore/core/test/unit/testutil/expression_test_util.h" // For test helpers -#include "Firestore/core/test/unit/testutil/testutil.h" // For test helpers like Value, Map -#include "gmock/gmock.h" // For matchers like Returns +#include "Firestore/core/src/api/expressions.h" +#include "Firestore/core/test/unit/testutil/expression_test_util.h" +#include "Firestore/core/test/unit/testutil/testutil.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" namespace firebase { diff --git a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc index 3a46b01514a..2b04e4c94b1 100644 --- a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc +++ b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc @@ -14,17 +14,16 @@ * limitations under the License. */ -#include // For std::function -#include // For std::numeric_limits -#include // For std::shared_ptr +#include +#include +#include #include -#include // For std::move #include #include "Firestore/core/src/api/expressions.h" -#include "Firestore/core/src/core/expressions_eval.h" -#include "Firestore/core/src/model/field_path.h" // Correct include for FieldPath -#include "Firestore/core/src/util/string_format.h" // Include for StringFormat +#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/model/field_path.h" +#include "Firestore/core/src/util/string_format.h" #include "Firestore/core/test/unit/testutil/expression_test_util.h" #include "Firestore/core/test/unit/testutil/testutil.h" #include "gmock/gmock.h" diff --git a/Firestore/core/test/unit/core/expressions/string_test.cc b/Firestore/core/test/unit/core/expressions/string_test.cc index dba96829ec1..fac036994fb 100644 --- a/Firestore/core/test/unit/core/expressions/string_test.cc +++ b/Firestore/core/test/unit/core/expressions/string_test.cc @@ -20,10 +20,8 @@ #include #include "Firestore/core/src/api/expressions.h" -#include "Firestore/core/src/core/expressions_eval.h" -#include "Firestore/core/src/model/value_util.h" #include "Firestore/core/test/unit/testutil/expression_test_util.h" -#include "Firestore/core/test/unit/testutil/testutil.h" // For Value, Bytes etc. +#include "Firestore/core/test/unit/testutil/testutil.h" #include "gmock/gmock.h" #include "gtest/gtest.h" diff --git a/Firestore/core/test/unit/testutil/expression_test_util.h b/Firestore/core/test/unit/testutil/expression_test_util.h index 616fbd64df8..c91c987c92d 100644 --- a/Firestore/core/test/unit/testutil/expression_test_util.h +++ b/Firestore/core/test/unit/testutil/expression_test_util.h @@ -17,20 +17,29 @@ #ifndef FIRESTORE_CORE_TEST_UNIT_TESTUTIL_EXPRESSION_TEST_UTIL_H_ #define FIRESTORE_CORE_TEST_UNIT_TESTUTIL_EXPRESSION_TEST_UTIL_H_ -#include // For std::sort -#include // For std::initializer_list -#include // For std::numeric_limits -#include // For std::shared_ptr, std::make_shared -#include // For std::ostream -#include // For std::string -#include // For std::move, std::pair +#include +#include +#include +#include +#include +#include +#include #include #include "Firestore/core/include/firebase/firestore/geo_point.h" #include "Firestore/core/include/firebase/firestore/timestamp.h" #include "Firestore/core/src/api/expressions.h" #include "Firestore/core/src/api/stages.h" -#include "Firestore/core/src/core/expressions_eval.h" +#include "Firestore/core/src/core/pipeline/aggregates.h" +#include "Firestore/core/src/core/pipeline/evaluation/arithmetic.h" +#include "Firestore/core/src/core/pipeline/evaluation/array.h" +#include "Firestore/core/src/core/pipeline/evaluation/comparison.h" +#include "Firestore/core/src/core/pipeline/evaluation/logical.h" +#include "Firestore/core/src/core/pipeline/evaluation/map.h" +#include "Firestore/core/src/core/pipeline/evaluation/string.h" +#include "Firestore/core/src/core/pipeline/evaluation/timestamp.h" +#include "Firestore/core/src/core/pipeline/evaluation/type.h" +#include "Firestore/core/src/core/pipeline/expression.h" #include "Firestore/core/src/model/database_id.h" #include "Firestore/core/src/model/document_key.h" #include "Firestore/core/src/model/mutable_document.h" @@ -40,10 +49,10 @@ #include "Firestore/core/src/nanopb/message.h" #include "Firestore/core/src/remote/serializer.h" #include "Firestore/core/src/util/hard_assert.h" -#include "Firestore/core/src/util/string_format.h" // For StringFormat +#include "Firestore/core/src/util/string_format.h" #include "Firestore/core/test/unit/testutil/testutil.h" -#include "absl/strings/escaping.h" // For absl::HexStringToBytes +#include "absl/strings/escaping.h" #include "gmock/gmock.h" #include "gtest/gtest.h" From 59df4b53da1d8252734ac9e2aad88aba09080109 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Mon, 1 Dec 2025 15:54:18 -0500 Subject: [PATCH 31/36] rename expression file --- .../Firestore.xcodeproj/project.pbxproj | 422 +++++++++--------- Firestore/core/src/api/expressions.cc | 2 +- Firestore/core/src/api/stages.cc | 2 +- ...aggregates.cc => aggregates_evaluation.cc} | 2 +- .../{aggregates.h => aggregates_evaluation.h} | 8 +- .../src/core/pipeline/evaluation/arithmetic.h | 2 +- .../core/src/core/pipeline/evaluation/array.h | 2 +- .../src/core/pipeline/evaluation/comparison.h | 2 +- .../src/core/pipeline/evaluation/logical.h | 2 +- .../core/src/core/pipeline/evaluation/map.h | 2 +- .../src/core/pipeline/evaluation/string.h | 2 +- .../src/core/pipeline/evaluation/timestamp.h | 2 +- .../core/src/core/pipeline/evaluation/type.h | 2 +- ...expression.cc => expression_evaluation.cc} | 4 +- .../{expression.h => expression_evaluation.h} | 6 +- Firestore/core/src/core/pipeline_util.cc | 2 +- .../unit/core/expressions/arithmetic_test.cc | 2 +- .../expressions/mirroring_semantics_test.cc | 2 +- .../test/unit/testutil/expression_test_util.h | 4 +- 19 files changed, 236 insertions(+), 236 deletions(-) rename Firestore/core/src/core/pipeline/{aggregates.cc => aggregates_evaluation.cc} (97%) rename Firestore/core/src/core/pipeline/{aggregates.h => aggregates_evaluation.h} (84%) rename Firestore/core/src/core/pipeline/{expression.cc => expression_evaluation.cc} (98%) rename Firestore/core/src/core/pipeline/{expression.h => expression_evaluation.h} (95%) diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj index 5a1dd41c53a..70ac64a12db 100644 --- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj +++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ 056542AD1D0F78E29E22EFA9 /* grpc_connection_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D9649021544D4F00EB9CFB /* grpc_connection_test.cc */; }; 0575F3004B896D94456A74CE /* status_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3CAA33F964042646FDDAF9F9 /* status_testing.cc */; }; 0595B5EBEB8F09952B72C883 /* logic_utils_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 28B45B2104E2DAFBBF86DBB7 /* logic_utils_test.cc */; }; + 05A18C838432F611F21F1C53 /* Pods_Firestore_IntegrationTests_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 949E444D7EAA5BE81BBE5E5E /* Pods_Firestore_IntegrationTests_macOS.framework */; }; 05D99904EA713414928DD920 /* query_listener_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7C3F995E040E9E9C5E8514BB /* query_listener_test.cc */; }; 062072B72773A055001655D7 /* AsyncAwaitIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 062072B62773A055001655D7 /* AsyncAwaitIntegrationTests.swift */; }; 062072B82773A055001655D7 /* AsyncAwaitIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 062072B62773A055001655D7 /* AsyncAwaitIntegrationTests.swift */; }; @@ -192,6 +193,7 @@ 16FF9073CA381CA43CA9BF29 /* FIRTransactionOptionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */; }; 1733601ECCEA33E730DEAF45 /* autoid_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54740A521FC913E500713A1A /* autoid_test.cc */; }; 17473086EBACB98CDC3CC65C /* view_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = C7429071B33BDF80A7FA2F8A /* view_test.cc */; }; + 175B5477F51147408A287F61 /* Pods_Firestore_IntegrationTests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DD0B43814F694A7004F307F /* Pods_Firestore_IntegrationTests_iOS.framework */; }; 17638F813B9B556FE7718C0C /* FIRQuerySnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04F202154AA00B64F25 /* FIRQuerySnapshotTests.mm */; }; 1792477DD2B3A1710BFD443F /* arithmetic_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 76EED4ED84056B623D92FE20 /* arithmetic_test.cc */; }; 17D5E2D389728F992297DA1F /* nested_properties_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8AC88AA2B929CFEC2656E37D /* nested_properties_test.cc */; }; @@ -249,7 +251,6 @@ 1DB3013C5FC736B519CD65A3 /* common.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 544129D221C2DDC800EFB9CC /* common.pb.cc */; }; 1DCA68BB2EF7A9144B35411F /* leveldb_opener_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 75860CD13AF47EB1EA39EC2F /* leveldb_opener_test.cc */; }; 1DCDED1F94EBC7F72FDBFC98 /* md5_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = E2E39422953DE1D3C7B97E77 /* md5_testing.cc */; }; - 1DE9E7D3143F10C34A42639C /* Pods_Firestore_IntegrationTests_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 253A7A96FFAA2C8A8754D3CF /* Pods_Firestore_IntegrationTests_macOS.framework */; }; 1E194F1CFDFE0265DF1CD5E6 /* garbage_collection_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = AAED89D7690E194EF3BA1132 /* garbage_collection_spec_test.json */; }; 1E2AE064CF32A604DC7BFD4D /* to_string_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B696858D2214B53900271095 /* to_string_test.cc */; }; 1E2D112B9376024258414CF0 /* disjunctive_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2BE59C9C2992E1A580D02935 /* disjunctive_test.cc */; }; @@ -328,6 +329,7 @@ 28E4B4A53A739AE2C9CF4159 /* FIRDocumentSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04B202154AA00B64F25 /* FIRDocumentSnapshotTests.mm */; }; 29243A4BBB2E2B1530A62C59 /* leveldb_transaction_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 88CF09277CFA45EE1273E3BA /* leveldb_transaction_test.cc */; }; 292BCC76AF1B916752764A8F /* leveldb_bundle_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8E9CD82E60893DDD7757B798 /* leveldb_bundle_cache_test.cc */; }; + 2951C96256ECD27C2165907A /* Pods_Firestore_Example_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E41D518EC9B6079252C063D /* Pods_Firestore_Example_macOS.framework */; }; 297DC2B3C1EB136D58F4BA9C /* byte_string_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5342CDDB137B4E93E2E85CCA /* byte_string_test.cc */; }; 298E0F8F6EB27AA36BA1CE76 /* FIRQueryUnitTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = FF73B39D04D1760190E6B84A /* FIRQueryUnitTests.mm */; }; 29954A3172DDFE5133D91E24 /* FSTLevelDBSpecTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E02C20213FFB00B64F25 /* FSTLevelDBSpecTests.mm */; }; @@ -402,12 +404,12 @@ 34B62A40BB56F9574B87B28B /* Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = D8E530B27D5641B9C26A452C /* Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json */; }; 34D69886DAD4A2029BFC5C63 /* precondition_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 549CCA5520A36E1F00BCEB75 /* precondition_test.cc */; }; 34E866DB52AAB7DB76B69A91 /* recovery_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 9C1AFCC9E616EC33D6E169CF /* recovery_spec_test.json */; }; + 352AA573D357554B9808D2CD /* Pods_Firestore_Tests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C6CD63A780B7E8F1EBF761 /* Pods_Firestore_Tests_iOS.framework */; }; 353E47129584B8DDF10138BD /* stream_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5B5414D28802BC76FDADABD6 /* stream_test.cc */; }; 35503DAC4FD0D765A2DE82A8 /* byte_stream_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 432C71959255C5DBDF522F52 /* byte_stream_test.cc */; }; 355A9171EF3F7AD44A9C60CB /* document_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB6B908320322E4D00CC290A /* document_test.cc */; }; 35C330499D50AC415B24C580 /* async_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 872C92ABD71B12784A1C5520 /* async_testing.cc */; }; 35DB74DFB2F174865BCCC264 /* leveldb_transaction_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 88CF09277CFA45EE1273E3BA /* leveldb_transaction_test.cc */; }; - 35EAE24071EAF2E69931B0F7 /* Pods_Firestore_Tests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 406BBAC409B5EB8531D366CA /* Pods_Firestore_Tests_tvOS.framework */; }; 35FEB53E165518C0DE155CB0 /* target_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 526D755F65AC676234F57125 /* target_test.cc */; }; 360EB1D691F9C19A21D0916F /* Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = D22D4C211AC32E4F8B4883DA /* Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json */; }; 36999FC1F37930E8C9B6DA25 /* stream_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5B5414D28802BC76FDADABD6 /* stream_test.cc */; }; @@ -465,12 +467,12 @@ 3E101CE56C70F06BA2FDD56C /* Validation_BloomFilterTest_MD5_50000_1_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 3841925AA60E13A027F565E6 /* Validation_BloomFilterTest_MD5_50000_1_membership_test_result.json */; }; 3E38E4B33855DD6CF7526225 /* bundle_serializer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5C2A94EE24E60543F62CC35 /* bundle_serializer_test.cc */; }; 3E5FD39FE7442883AB3CE1F2 /* Validation_BloomFilterTest_MD5_1_01_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 5C68EE4CB94C0DD6E333F546 /* Validation_BloomFilterTest_MD5_1_01_membership_test_result.json */; }; + 3E81E93349135A3E814376F9 /* Pods_Firestore_Example_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82FFAF9DBBA0F7ABD2A0AEAD /* Pods_Firestore_Example_iOS.framework */; }; 3F3C2DAD9F9326BF789B1C96 /* serializer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 61F72C5520BC48FD001A68CB /* serializer_test.cc */; }; 3F4B6300198FD78E7B19BC5A /* strerror_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 358C3B5FE573B1D60A4F7592 /* strerror_test.cc */; }; 3F6C9F8A993CF4B0CD51E7F0 /* lru_garbage_collector_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 277EAACC4DD7C21332E8496A /* lru_garbage_collector_test.cc */; }; 3FF88C11276449F00F79AF48 /* status_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3CAA33F964042646FDDAF9F9 /* status_testing.cc */; }; 3FFFC1FE083D8BE9C4D9A148 /* string_util_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB380CFC201A2EE200D97691 /* string_util_test.cc */; }; - 403B1ABF47F9FFE876F6DDCA /* Pods_Firestore_Example_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A17F8CBAFA07CAE9FFBC8BC5 /* Pods_Firestore_Example_macOS.framework */; }; 40431BF2A368D0C891229F6E /* FSTMemorySpecTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E02F20213FFC00B64F25 /* FSTMemorySpecTests.mm */; }; 409B29C81132718B36BF2497 /* Validation_BloomFilterTest_MD5_5000_0001_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = C8582DFD74E8060C7072104B /* Validation_BloomFilterTest_MD5_5000_0001_membership_test_result.json */; }; 409C0F2BFC2E1BECFFAC4D32 /* testutil.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54A0352820A3B3BD003E0143 /* testutil.cc */; }; @@ -719,7 +721,6 @@ 55427A6CFFB22E069DCC0CC4 /* target_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 526D755F65AC676234F57125 /* target_test.cc */; }; 555161D6DB2DDC8B57F72A70 /* comparison_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 548DB928200D59F600E00ABC /* comparison_test.cc */; }; 5556B648B9B1C2F79A706B4F /* common.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 544129D221C2DDC800EFB9CC /* common.pb.cc */; }; - 55B9A6ACDF95D356EA501D92 /* Pods_Firestore_Example_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB5A5E6DD07DA3EB7AD46CA7 /* Pods_Firestore_Example_iOS.framework */; }; 55E84644D385A70E607A0F91 /* leveldb_local_store_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5FF903AEFA7A3284660FA4C5 /* leveldb_local_store_test.cc */; }; 568EC1C0F68A7B95E57C8C6C /* leveldb_key_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54995F6E205B6E12004EFFA0 /* leveldb_key_test.cc */; }; 56D85436D3C864B804851B15 /* string_format_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFD366B783AE27B9E79EE7A /* string_format_apple_test.mm */; }; @@ -743,7 +744,6 @@ 5A44725457D6B7805FD66EEB /* bundle_loader_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = A853C81A6A5A51C9D0389EDA /* bundle_loader_test.cc */; }; 5ACF26A3B0A33784CC525FB0 /* aggregate_query_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AF924C79F49F793992A84879 /* aggregate_query_test.cc */; }; 5AFA1055E8F6B4E4B1CCE2C4 /* bundle_builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4F5B96F3ABCD2CA901DB1CD4 /* bundle_builder.cc */; }; - 5AFB773E190A8FDC6C2D3DB6 /* Pods_Firestore_Benchmarks_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC758DA6CABF213979029A2B /* Pods_Firestore_Benchmarks_iOS.framework */; }; 5B0E2D0595BE30B2320D96F1 /* EncodableFieldValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1235769122B7E915007DDFA9 /* EncodableFieldValueTests.swift */; }; 5B4391097A6DF86EC3801DEE /* string_win_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 79507DF8378D3C42F5B36268 /* string_win_test.cc */; }; 5B62003FEA9A3818FDF4E2DD /* document_key_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6152AD5202A5385000E5744 /* document_key_test.cc */; }; @@ -987,7 +987,6 @@ 7A2D523AEF58B1413CC8D64F /* query_engine_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B8A853940305237AFDA8050B /* query_engine_test.cc */; }; 7A3BE0ED54933C234FDE23D1 /* leveldb_util_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 332485C4DCC6BA0DBB5E31B7 /* leveldb_util_test.cc */; }; 7A66A2CB5CF33F0C28202596 /* status_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54A0352C20A3B3D7003E0143 /* status_test.cc */; }; - 7A6BDBD2C373800BAA202526 /* Pods_Firestore_Example_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A7EE8E1466BA54F199B0991 /* Pods_Firestore_Example_tvOS.framework */; }; 7A7DB86955670B85B4514A1F /* Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 4B59C0A7B2A4548496ED4E7D /* Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json */; }; 7A7EC216A0015D7620B4FF3E /* string_format_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFD366B783AE27B9E79EE7A /* string_format_apple_test.mm */; }; 7A8DF35E7DB4278E67E6BDB3 /* snapshot_version_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = ABA495B9202B7E79008A7851 /* snapshot_version_test.cc */; }; @@ -1019,6 +1018,7 @@ 7DED491019248CE9B9E9EB50 /* FSTLevelDBSpecTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E02C20213FFB00B64F25 /* FSTLevelDBSpecTests.mm */; }; 7E1B1335B2EC566FB25B710C /* Validation_BloomFilterTest_MD5_50000_01_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = C8FB22BCB9F454DA44BA80C8 /* Validation_BloomFilterTest_MD5_50000_01_membership_test_result.json */; }; 7E82D412BB56728BEBB7EF46 /* bundle_serializer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5C2A94EE24E60543F62CC35 /* bundle_serializer_test.cc */; }; + 7E873E95A1C12646B7C22502 /* Pods_Firestore_Benchmarks_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29656CF5FBF6FA0230D7B6EA /* Pods_Firestore_Benchmarks_iOS.framework */; }; 7E97B0F04E25610FF37E9259 /* memory_target_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2286F308EFB0534B1BDE05B9 /* memory_target_cache_test.cc */; }; 7EAB3129A58368EE4BD449ED /* leveldb_migrations_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EF83ACD5E1E9F25845A9ACED /* leveldb_migrations_test.cc */; }; 7EF540911720DAAF516BEDF0 /* query_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B9C261C26C5D311E1E3C0CB9 /* query_test.cc */; }; @@ -1150,6 +1150,7 @@ 94854FAEAEA75A1AC77A0515 /* memory_bundle_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB4AB1388538CD3CB19EB028 /* memory_bundle_cache_test.cc */; }; 94BBB23B93E449D03FA34F87 /* mutation_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3068AA9DFBBA86C1FE2A946E /* mutation_queue_test.cc */; }; 94C86F03FF86690307F28182 /* Validation_BloomFilterTest_MD5_5000_0001_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = C8582DFD74E8060C7072104B /* Validation_BloomFilterTest_MD5_5000_0001_membership_test_result.json */; }; + 94EC0C2B013259594DA44983 /* Pods_Firestore_Example_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 56DFA1A5F0D4F7CE4F014158 /* Pods_Firestore_Example_tvOS.framework */; }; 95490163C98C4F8AFD019730 /* comparison_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 87DD1A65EBA9FFC1FFAAE657 /* comparison_test.cc */; }; 95C0F55813DA51E6B8C439E1 /* status_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5493A423225F9990006DE7BA /* status_apple_test.mm */; }; 95CE3F5265B9BB7297EE5A6B /* lru_garbage_collector_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 277EAACC4DD7C21332E8496A /* lru_garbage_collector_test.cc */; }; @@ -1173,9 +1174,9 @@ 98FE82875A899A40A98AAC22 /* leveldb_opener_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 75860CD13AF47EB1EA39EC2F /* leveldb_opener_test.cc */; }; 990EC10E92DADB7D86A4BEE3 /* string_format_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54131E9620ADE678001DF3FF /* string_format_test.cc */; }; 992DD6779C7A166D3A22E749 /* firebase_app_check_credentials_provider_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = F119BDDF2F06B3C0883B8297 /* firebase_app_check_credentials_provider_test.mm */; }; + 9948EC749F74B2FA50E96845 /* Pods_Firestore_Tests_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2696F7160BC0525999F33F85 /* Pods_Firestore_Tests_macOS.framework */; }; 9966167103B9714723A88669 /* Validation_BloomFilterTest_MD5_50000_1_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 3841925AA60E13A027F565E6 /* Validation_BloomFilterTest_MD5_50000_1_membership_test_result.json */; }; 99F97B28DA546D42AB14214B /* comparison_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 87DD1A65EBA9FFC1FFAAE657 /* comparison_test.cc */; }; - 9A13350EF5C115DF314BFE1D /* Pods_Firestore_Tests_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 10F64BFFE86C4316F3F8AD95 /* Pods_Firestore_Tests_macOS.framework */; }; 9A29D572C64CA1FA62F591D4 /* FIRQueryTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E069202154D500B64F25 /* FIRQueryTests.mm */; }; 9A75A9413ED1D994DC6F37C6 /* bloom_filter_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = A2E6F09AD1EE0A6A452E9A08 /* bloom_filter_test.cc */; }; 9A7CF567C6FF0623EB4CFF64 /* datastore_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3167BD972EFF8EC636530E59 /* datastore_test.cc */; }; @@ -1230,7 +1231,6 @@ A478FDD7C3F48FBFDDA7D8F5 /* leveldb_mutation_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5C7942B6244F4C416B11B86C /* leveldb_mutation_queue_test.cc */; }; A4AD189BDEF7A609953457A6 /* leveldb_key_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54995F6E205B6E12004EFFA0 /* leveldb_key_test.cc */; }; A4ECA8335000CBDF94586C94 /* FSTDatastoreTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E07E202154EC00B64F25 /* FSTDatastoreTests.mm */; }; - A4F2B68E7EFADB0EB443CFF8 /* Pods_Firestore_Tests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8294C2063C0096AE5E43F6DF /* Pods_Firestore_Tests_iOS.framework */; }; A5175CA2E677E13CC5F23D72 /* document_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB6B908320322E4D00CC290A /* document_test.cc */; }; A53C9BA3D0E366DCCDD640BF /* canonify_eq_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 51004EAF5EE01ADCE8FE3788 /* canonify_eq_test.cc */; }; A55266E6C986251D283CE948 /* FIRCursorTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E070202154D600B64F25 /* FIRCursorTests.mm */; }; @@ -1343,6 +1343,7 @@ B40EDE2B1B228ED59CF62788 /* byte_stream_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7628664347B9C96462D4BF17 /* byte_stream_apple_test.mm */; }; B41B17163DD9A421F35DE1A9 /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 57F8EE51B5EFC9FAB185B66C /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json */; }; B43014A0517F31246419E08A /* resume_token_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA12A41F315EE100DD57A1 /* resume_token_spec_test.json */; }; + B4321FCCCFBC787BF1109FC5 /* Pods_Firestore_Tests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8B9310A8C2FA2201E1261B4 /* Pods_Firestore_Tests_tvOS.framework */; }; B46E778F9E40864B5D2B2F1C /* leveldb_transaction_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 88CF09277CFA45EE1273E3BA /* leveldb_transaction_test.cc */; }; B491EF0E70DC0542644F623E /* Validation_BloomFilterTest_MD5_500_1_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 8AB49283E544497A9C5A0E59 /* Validation_BloomFilterTest_MD5_500_1_membership_test_result.json */; }; B4C675BE9030D5C7D19C4D19 /* ordered_code_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB380D03201BC6E400D97691 /* ordered_code_test.cc */; }; @@ -1438,6 +1439,7 @@ BFBE4732E93E38317B110778 /* index_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 8C7278B604B8799F074F4E8C /* index_spec_test.json */; }; BFCDC78CD851F109EB7A1422 /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 57F8EE51B5EFC9FAB185B66C /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json */; }; BFEAC4151D3AA8CE1F92CC2D /* FSTSpecTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E03020213FFC00B64F25 /* FSTSpecTests.mm */; }; + BFFF80B66D9D8BDB91844575 /* Pods_Firestore_IntegrationTests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E99993350B9F360190C6A886 /* Pods_Firestore_IntegrationTests_tvOS.framework */; }; C02A969BF4BB63ABCB531B4B /* create_noop_connectivity_monitor.cc in Sources */ = {isa = PBXBuildFile; fileRef = CF39535F2C41AB0006FA6C0E /* create_noop_connectivity_monitor.cc */; }; C06E54352661FCFB91968640 /* mutation_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3068AA9DFBBA86C1FE2A946E /* mutation_queue_test.cc */; }; C099AEC05D44976755BA32A2 /* thread_safe_memoizer_testing_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EA10515F99A42D71DA2D2841 /* thread_safe_memoizer_testing_test.cc */; }; @@ -1474,7 +1476,6 @@ C5655568EC2A9F6B5E6F9141 /* firestore.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 544129D421C2DDC800EFB9CC /* firestore.pb.cc */; }; C57B15CADD8C3E806B154C19 /* task_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 899FC22684B0F7BEEAE13527 /* task_test.cc */; }; C5F1E2220E30ED5EAC9ABD9E /* mutation.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 618BBE8220B89AAC00B5BCE7 /* mutation.pb.cc */; }; - C5F7739063B1515A8628B370 /* Pods_Firestore_IntegrationTests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 453332546740E27077C65FDC /* Pods_Firestore_IntegrationTests_tvOS.framework */; }; C602E27459408B90A0DF2AA0 /* Validation_BloomFilterTest_MD5_50000_0001_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = A5D9044B72061CAF284BC9E4 /* Validation_BloomFilterTest_MD5_50000_0001_bloom_filter_proto.json */; }; C663A8B74B57FD84717DEA21 /* delayed_constructor_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D0A6E9136804A41CEC9D55D4 /* delayed_constructor_test.cc */; }; C6BF529243414C53DF5F1012 /* memory_local_store_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F6CA0C5638AB6627CB5B4CF4 /* memory_local_store_test.cc */; }; @@ -1498,7 +1499,6 @@ C97CD9EA59E9BBEFE17E94D6 /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 57F8EE51B5EFC9FAB185B66C /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json */; }; C985030E45AB19081D0273BE /* Validation_BloomFilterTest_MD5_1_1_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 3FDD0050CA08C8302400C5FB /* Validation_BloomFilterTest_MD5_1_1_bloom_filter_proto.json */; }; C9C9A92E1734A097BE0670AF /* Validation_BloomFilterTest_MD5_5000_0001_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 728F617782600536F2561463 /* Validation_BloomFilterTest_MD5_5000_0001_bloom_filter_proto.json */; }; - C9D01A1A30CD147F28493698 /* Pods_Firestore_IntegrationTests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9C9F60851E52197B30E0AF9 /* Pods_Firestore_IntegrationTests_iOS.framework */; }; C9F96C511F45851D38EC449C /* status.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 618BBE9920B89AAC00B5BCE7 /* status.pb.cc */; }; CA2392732BA7F8985699313D /* Validation_BloomFilterTest_MD5_1_1_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 3369AC938F82A70685C5ED58 /* Validation_BloomFilterTest_MD5_1_1_membership_test_result.json */; }; CA989C0E6020C372A62B7062 /* testutil.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54A0352820A3B3BD003E0143 /* testutil.cc */; }; @@ -1904,10 +1904,10 @@ /* Begin PBXFileReference section */ 014C60628830D95031574D15 /* random_access_queue_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = random_access_queue_test.cc; sourceTree = ""; }; 01D10113ECC5B446DB35E96D /* byte_stream_cpp_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = byte_stream_cpp_test.cc; sourceTree = ""; }; - 03BD47161789F26754D3B958 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Benchmarks_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS.release.xcconfig"; sourceTree = ""; }; 0458BABD8F8738AD16F4A2FE /* array_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = array_test.cc; path = expressions/array_test.cc; sourceTree = ""; }; 045D39C4A7D52AF58264240F /* remote_document_cache_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = remote_document_cache_test.h; sourceTree = ""; }; 0473AFFF5567E667A125347B /* ordered_code_benchmark.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = ordered_code_benchmark.cc; sourceTree = ""; }; + 04F95FB0B1123006B5DA8153 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Benchmarks_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS.release.xcconfig"; sourceTree = ""; }; 062072B62773A055001655D7 /* AsyncAwaitIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncAwaitIntegrationTests.swift; sourceTree = ""; }; 0840319686A223CC4AD3FAB1 /* leveldb_remote_document_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_remote_document_cache_test.cc; sourceTree = ""; }; 09885253E010E281EC2773C4 /* where_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = where_test.cc; path = pipeline/where_test.cc; sourceTree = ""; }; @@ -1915,7 +1915,6 @@ 0D964D4936953635AC7E0834 /* Validation_BloomFilterTest_MD5_1_01_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_1_01_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_1_01_bloom_filter_proto.json; sourceTree = ""; }; 0E73D03B9C02CAC7BEBAFA86 /* TestHelper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TestHelper.swift; path = TestHelper/TestHelper.swift; sourceTree = ""; }; 0EE5300F8233D14025EF0456 /* string_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = string_apple_test.mm; sourceTree = ""; }; - 10F64BFFE86C4316F3F8AD95 /* Pods_Firestore_Tests_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1235769122B7E915007DDFA9 /* EncodableFieldValueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncodableFieldValueTests.swift; sourceTree = ""; }; 1235769422B86E65007DDFA9 /* FirestoreEncoderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirestoreEncoderTests.swift; sourceTree = ""; }; 124C932B22C1642C00CA8C2D /* CodableIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableIntegrationTests.swift; sourceTree = ""; }; @@ -1937,16 +1936,16 @@ 1E0C7C0DCD2790019E66D8CC /* bloom_filter.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = bloom_filter.pb.cc; sourceTree = ""; }; 1F50E872B3F117A674DA8E94 /* index_backfiller_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = index_backfiller_test.cc; sourceTree = ""; }; 1F78CD3208A1D5885B4C134E /* field_behavior.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = field_behavior.pb.cc; sourceTree = ""; }; + 20C55A10362C9BDE9FB8C5E1 /* Pods-Firestore_Example_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS.release.xcconfig"; sourceTree = ""; }; 214877F52A705012D6720CA0 /* object_value_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = object_value_test.cc; sourceTree = ""; }; 2286F308EFB0534B1BDE05B9 /* memory_target_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_target_cache_test.cc; sourceTree = ""; }; 24F0F49F016E65823E0075DB /* field_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = field_test.cc; path = expressions/field_test.cc; sourceTree = ""; }; - 25191D04F1D477571A7D3740 /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Benchmarks_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS.debug.xcconfig"; sourceTree = ""; }; - 253A7A96FFAA2C8A8754D3CF /* Pods_Firestore_IntegrationTests_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2696F7160BC0525999F33F85 /* Pods_Firestore_Tests_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 26DDBA115DEB88631B93F203 /* thread_safe_memoizer_testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = thread_safe_memoizer_testing.h; sourceTree = ""; }; 277EAACC4DD7C21332E8496A /* lru_garbage_collector_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = lru_garbage_collector_test.cc; sourceTree = ""; }; 28034BA61A7395543F1508B3 /* maybe_document.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = maybe_document.pb.cc; sourceTree = ""; }; 28B45B2104E2DAFBBF86DBB7 /* logic_utils_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = logic_utils_test.cc; sourceTree = ""; }; - 29749DC3DADA38CAD1EB9AC4 /* Pods-Firestore_Tests_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS.debug.xcconfig"; sourceTree = ""; }; + 29656CF5FBF6FA0230D7B6EA /* Pods_Firestore_Benchmarks_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Benchmarks_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2996F8E339AD187C2C5068DE /* utils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = utils.h; path = pipeline/utils.h; sourceTree = ""; }; 29D9C76922DAC6F710BC1EF4 /* memory_document_overlay_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_document_overlay_cache_test.cc; sourceTree = ""; }; 2A0CF41BA5AED6049B0BEB2C /* objc_type_traits_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = objc_type_traits_apple_test.mm; sourceTree = ""; }; @@ -1959,6 +1958,7 @@ 3081975D68903993303FA256 /* collection_group_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = collection_group_test.cc; path = pipeline/collection_group_test.cc; sourceTree = ""; }; 312E4667E3D994592C77B63C /* byte_stream_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = byte_stream_test.h; sourceTree = ""; }; 3167BD972EFF8EC636530E59 /* datastore_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = datastore_test.cc; sourceTree = ""; }; + 319C19479B01F7DEEAD9774A /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS.release.xcconfig"; sourceTree = ""; }; 32C7CB095CD53D07E98D74B8 /* bundle.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = bundle.pb.h; sourceTree = ""; }; 332485C4DCC6BA0DBB5E31B7 /* leveldb_util_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_util_test.cc; sourceTree = ""; }; 3355BE9391CC4857AF0BDAE3 /* DatabaseTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DatabaseTests.swift; sourceTree = ""; }; @@ -1973,7 +1973,6 @@ 3FBAA6F05C0B46A522E3B5A7 /* bundle_cache_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = bundle_cache_test.h; sourceTree = ""; }; 3FDD0050CA08C8302400C5FB /* Validation_BloomFilterTest_MD5_1_1_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_1_1_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_1_1_bloom_filter_proto.json; sourceTree = ""; }; 403DBF6EFB541DFD01582AA3 /* path_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = path_test.cc; sourceTree = ""; }; - 406BBAC409B5EB8531D366CA /* Pods_Firestore_Tests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 40F9D09063A07F710811A84F /* value_util_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = value_util_test.cc; sourceTree = ""; }; 4132F30044D5DF1FB15B2A9D /* fake_credentials_provider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = fake_credentials_provider.h; sourceTree = ""; }; 428662F00938E9E21F7080D7 /* explain_stats.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = explain_stats.pb.cc; sourceTree = ""; }; @@ -1981,18 +1980,20 @@ 4334F87873015E3763954578 /* status_testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = status_testing.h; sourceTree = ""; }; 4375BDCDBCA9938C7F086730 /* Validation_BloomFilterTest_MD5_5000_1_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_5000_1_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_5000_1_bloom_filter_proto.json; sourceTree = ""; }; 444B7AB3F5A2929070CB1363 /* hard_assert_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = hard_assert_test.cc; sourceTree = ""; }; - 453332546740E27077C65FDC /* Pods_Firestore_IntegrationTests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4564AD9C55EC39C080EB9476 /* globals_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = globals_cache_test.cc; sourceTree = ""; }; + 459864A45E38975067B09B19 /* Pods-Firestore_Example_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS.release.xcconfig"; sourceTree = ""; }; 478DC75A0DCA6249A616DD30 /* Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json; sourceTree = ""; }; 48D0915834C3D234E5A875A9 /* grpc_stream_tester.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = grpc_stream_tester.h; sourceTree = ""; }; 4B0A3187AAD8B02135E80C2E /* collection_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = collection_test.cc; path = pipeline/collection_test.cc; sourceTree = ""; }; - 4B2C0786117A4C34F4CD0C6A /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS.release.xcconfig"; sourceTree = ""; }; 4B3E4A77493524333133C5DC /* Validation_BloomFilterTest_MD5_50000_1_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_50000_1_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_50000_1_bloom_filter_proto.json; sourceTree = ""; }; 4B59C0A7B2A4548496ED4E7D /* Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json; sourceTree = ""; }; + 4BB169579995C73A8BF4D981 /* Pods-Firestore_Tests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS.debug.xcconfig"; sourceTree = ""; }; 4BD051DBE754950FEAC7A446 /* Validation_BloomFilterTest_MD5_500_01_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_500_01_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_500_01_bloom_filter_proto.json; sourceTree = ""; }; 4C73C0CC6F62A90D8573F383 /* string_apple_benchmark.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = string_apple_benchmark.mm; sourceTree = ""; }; 4D65F6E69993611D47DC8E7C /* SnapshotListenerSourceTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SnapshotListenerSourceTests.swift; sourceTree = ""; }; 4D9E51DA7A275D8B1CAEAEB2 /* listen_source_spec_test.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; path = listen_source_spec_test.json; sourceTree = ""; }; + 4DD0B43814F694A7004F307F /* Pods_Firestore_IntegrationTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4EAA1E2AC6B9AD4D3876C451 /* Pods-Firestore_Tests_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS.debug.xcconfig"; sourceTree = ""; }; 4F5B96F3ABCD2CA901DB1CD4 /* bundle_builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = bundle_builder.cc; sourceTree = ""; }; 51004EAF5EE01ADCE8FE3788 /* canonify_eq_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = canonify_eq_test.cc; path = pipeline/canonify_eq_test.cc; sourceTree = ""; }; 526D755F65AC676234F57125 /* target_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = target_test.cc; sourceTree = ""; }; @@ -2097,18 +2098,18 @@ 54E9281E1F33950B00C1953E /* FSTIntegrationTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSTIntegrationTestCase.h; sourceTree = ""; }; 54E9282A1F339CAD00C1953E /* XCTestCase+Await.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCTestCase+Await.h"; sourceTree = ""; }; 54EB764C202277B30088B8F3 /* array_sorted_map_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = array_sorted_map_test.cc; sourceTree = ""; }; + 56DFA1A5F0D4F7CE4F014158 /* Pods_Firestore_Example_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 57F8EE51B5EFC9FAB185B66C /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json; sourceTree = ""; }; 584AE2C37A55B408541A6FF3 /* remote_event_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = remote_event_test.cc; sourceTree = ""; }; 59BF06E5A4988F9F949DD871 /* PipelineApiTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PipelineApiTests.swift; sourceTree = ""; }; 5B5414D28802BC76FDADABD6 /* stream_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = stream_test.cc; sourceTree = ""; }; 5B96CC29E9946508F022859C /* Validation_BloomFilterTest_MD5_50000_0001_membership_test_result.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_50000_0001_membership_test_result.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_50000_0001_membership_test_result.json; sourceTree = ""; }; - 5BAD4FE9D876483DDAD34D96 /* Pods-Firestore_Tests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS.release.xcconfig"; sourceTree = ""; }; 5C68EE4CB94C0DD6E333F546 /* Validation_BloomFilterTest_MD5_1_01_membership_test_result.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_1_01_membership_test_result.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_1_01_membership_test_result.json; sourceTree = ""; }; 5C6DEA63FBDE19D841291723 /* memory_globals_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_globals_cache_test.cc; sourceTree = ""; }; - 5C767F7D43A603B557327513 /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS.debug.xcconfig"; sourceTree = ""; }; 5C7942B6244F4C416B11B86C /* leveldb_mutation_queue_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_mutation_queue_test.cc; sourceTree = ""; }; 5CAE131920FFFED600BE9A4A /* Firestore_Benchmarks_iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Firestore_Benchmarks_iOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5CAE131D20FFFED600BE9A4A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5DC11E3981B81DDFF8A4453B /* Pods-Firestore_Tests_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS.release.xcconfig"; sourceTree = ""; }; 5E19B9B2105BA618DA9EE99C /* query_engine_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = query_engine_test.h; sourceTree = ""; }; 5FF903AEFA7A3284660FA4C5 /* leveldb_local_store_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_local_store_test.cc; sourceTree = ""; }; 6003F58A195388D20070C39A /* Firestore_Example_iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Firestore_Example_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2147,7 +2148,6 @@ 620C1427763BA5D3CCFB5A1F /* BridgingHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = BridgingHeader.h; sourceTree = ""; }; 621D620928F9CE7400D2FA26 /* QueryIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryIntegrationTests.swift; sourceTree = ""; }; 6271643B2ED4D5EE00D2CD1D /* RealtimePipelineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimePipelineTests.swift; sourceTree = ""; }; - 62CF8E2E7611B285B46228FE /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS.release.xcconfig"; sourceTree = ""; }; 62E54B832A9E910A003347C8 /* IndexingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndexingTests.swift; sourceTree = ""; }; 63136A2371C0C013EC7A540C /* target_index_matcher_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = target_index_matcher_test.cc; sourceTree = ""; }; 64AA92CFA356A2360F3C5646 /* filesystem_testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = filesystem_testing.h; sourceTree = ""; }; @@ -2155,6 +2155,8 @@ 65AF0AB593C3AD81A1F1A57E /* FIRCompositeIndexQueryTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRCompositeIndexQueryTests.mm; sourceTree = ""; }; 67786C62C76A740AEDBD8CD3 /* FSTTestingHooks.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FSTTestingHooks.h; sourceTree = ""; }; 6A7A30A2DB3367E08939E789 /* bloom_filter.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = bloom_filter.pb.h; sourceTree = ""; }; + 6ABFEF8FB2361EEE737CB120 /* Pods-Firestore_Example_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS.debug.xcconfig"; sourceTree = ""; }; + 6CA462CE027855D254A69006 /* Pods-Firestore_Example_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS.release.xcconfig"; sourceTree = ""; }; 6E42FA109D363EA7F3387AAE /* thread_safe_memoizer_testing.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = thread_safe_memoizer_testing.cc; sourceTree = ""; }; 6E8302DE210222ED003E1EA3 /* FSTFuzzTestFieldPath.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSTFuzzTestFieldPath.h; sourceTree = ""; }; 6E8302DF21022309003E1EA3 /* FSTFuzzTestFieldPath.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTFuzzTestFieldPath.mm; sourceTree = ""; }; @@ -2167,8 +2169,6 @@ 6EDD3B5E20BF24D000C33877 /* FSTFuzzTestsPrincipal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTFuzzTestsPrincipal.mm; sourceTree = ""; }; 6F57521E161450FAF89075ED /* event_manager_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = event_manager_test.cc; sourceTree = ""; }; 6F5B6C1399F92FD60F2C582B /* nanopb_util_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = nanopb_util_test.cc; path = nanopb/nanopb_util_test.cc; sourceTree = ""; }; - 708BC2920AEF83DC6630887E /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS.debug.xcconfig"; sourceTree = ""; }; - 708CD87D3C1E72E63229AB09 /* Pods-Firestore_Tests_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS.release.xcconfig"; sourceTree = ""; }; 71140E5D09C6E76F7C71B2FC /* fake_target_metadata_provider.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = fake_target_metadata_provider.cc; sourceTree = ""; }; 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 728F617782600536F2561463 /* Validation_BloomFilterTest_MD5_5000_0001_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_5000_0001_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_5000_0001_bloom_filter_proto.json; sourceTree = ""; }; @@ -2180,6 +2180,7 @@ 75860CD13AF47EB1EA39EC2F /* leveldb_opener_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_opener_test.cc; sourceTree = ""; }; 75E24C5CD7BC423D48713100 /* counting_query_engine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = counting_query_engine.h; sourceTree = ""; }; 7628664347B9C96462D4BF17 /* byte_stream_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = byte_stream_apple_test.mm; sourceTree = ""; }; + 765CEDF282B8255A337CEF80 /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig"; sourceTree = ""; }; 76EED4ED84056B623D92FE20 /* arithmetic_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = arithmetic_test.cc; path = expressions/arithmetic_test.cc; sourceTree = ""; }; 776530F066E788C355B78457 /* FIRBundlesTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRBundlesTests.mm; sourceTree = ""; }; 78EE0BFC7E60C4929458A0EA /* resource.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = resource.pb.h; sourceTree = ""; }; @@ -2192,9 +2193,9 @@ 7C3F995E040E9E9C5E8514BB /* query_listener_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = query_listener_test.cc; sourceTree = ""; }; 7C5C40C7BFBB86032F1DC632 /* FSTExceptionCatcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FSTExceptionCatcher.h; sourceTree = ""; }; 7EB299CF85034F09CFD6F3FD /* remote_document_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = remote_document_cache_test.cc; sourceTree = ""; }; - 81DFB7DE556603F7FDEDCA84 /* Pods-Firestore_Example_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS.debug.xcconfig"; sourceTree = ""; }; - 8294C2063C0096AE5E43F6DF /* Pods_Firestore_Tests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 82DF854A7238D538FA53C908 /* timestamp_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = timestamp_test.cc; path = expressions/timestamp_test.cc; sourceTree = ""; }; + 82FFAF9DBBA0F7ABD2A0AEAD /* Pods_Firestore_Example_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 831CE94805EAC3F88B9019DA /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS.debug.xcconfig"; sourceTree = ""; }; 84076EADF6872C78CDAC7291 /* bundle_builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = bundle_builder.h; sourceTree = ""; }; 861684E49DAC993D153E60D0 /* PipelineTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PipelineTests.swift; sourceTree = ""; }; 86C7F725E6E1DA312807D8D3 /* explain_stats.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = explain_stats.pb.h; sourceTree = ""; }; @@ -2202,7 +2203,6 @@ 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 87553338E42B8ECA05BA987E /* grpc_stream_tester.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = grpc_stream_tester.cc; sourceTree = ""; }; 87DD1A65EBA9FFC1FFAAE657 /* comparison_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = comparison_test.cc; path = expressions/comparison_test.cc; sourceTree = ""; }; - 88B7F25F26338EB9C03AE440 /* Pods-Firestore_Example_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS.release.xcconfig"; sourceTree = ""; }; 88CF09277CFA45EE1273E3BA /* leveldb_transaction_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_transaction_test.cc; sourceTree = ""; }; 899FC22684B0F7BEEAE13527 /* task_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = task_test.cc; sourceTree = ""; }; 8A41BBE832158C76BE901BC9 /* mutation_queue_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = mutation_queue_test.h; sourceTree = ""; }; @@ -2212,34 +2212,33 @@ 8C058C8BE2723D9A53CCD64B /* persistence_testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = persistence_testing.h; sourceTree = ""; }; 8C7278B604B8799F074F4E8C /* index_spec_test.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; path = index_spec_test.json; sourceTree = ""; }; 8D9892F204959C50613F16C8 /* FSTUserDataReaderTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTUserDataReaderTests.mm; sourceTree = ""; }; + 8DB38D2B14D3955ACA3F3952 /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS.release.xcconfig"; sourceTree = ""; }; 8E002F4AD5D9B6197C940847 /* Firestore.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Firestore.podspec; path = ../Firestore.podspec; sourceTree = ""; }; + 8E41D518EC9B6079252C063D /* Pods_Firestore_Example_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8E9CD82E60893DDD7757B798 /* leveldb_bundle_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_bundle_cache_test.cc; sourceTree = ""; }; 8EF6A33BC2D84233C355F1D0 /* memory_query_engine_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_query_engine_test.cc; sourceTree = ""; }; 8F1A7B4158D9DD76EE4836BF /* load_bundle_task_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = load_bundle_task_test.cc; path = api/load_bundle_task_test.cc; sourceTree = ""; }; 8FA60B08D59FEA0D6751E87F /* empty_credentials_provider_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = empty_credentials_provider_test.cc; path = credentials/empty_credentials_provider_test.cc; sourceTree = ""; }; 9098A0C535096F2EE9C35DE0 /* create_noop_connectivity_monitor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = create_noop_connectivity_monitor.h; sourceTree = ""; }; 9113B6F513D0473AEABBAF1F /* persistence_testing.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = persistence_testing.cc; sourceTree = ""; }; + 949E444D7EAA5BE81BBE5E5E /* Pods_Firestore_IntegrationTests_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9765D47FA12FA283F4EFAD02 /* memory_lru_garbage_collector_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_lru_garbage_collector_test.cc; sourceTree = ""; }; 99434327614FEFF7F7DC88EC /* counting_query_engine.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = counting_query_engine.cc; sourceTree = ""; }; - 99DD94DE29B06444E0C7CBAC /* Pods-Firestore_Example_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS.debug.xcconfig"; sourceTree = ""; }; - 9A7EE8E1466BA54F199B0991 /* Pods_Firestore_Example_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9B0B005A79E765AF02793DCE /* schedule_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = schedule_test.cc; sourceTree = ""; }; 9C1AFCC9E616EC33D6E169CF /* recovery_spec_test.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; path = recovery_spec_test.json; sourceTree = ""; }; 9CFD366B783AE27B9E79EE7A /* string_format_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = string_format_apple_test.mm; sourceTree = ""; }; + 9DE6467395E0973563A0BF9D /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS.debug.xcconfig"; sourceTree = ""; }; 9E60C06991E3D28A0F70DD8D /* globals_cache_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = globals_cache_test.h; sourceTree = ""; }; 9F12A488C443DBCCEC54DB61 /* pipeline_util_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = pipeline_util_test.cc; sourceTree = ""; }; A002425BC4FC4E805F4175B6 /* testing_hooks_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = testing_hooks_test.cc; sourceTree = ""; }; A082AFDD981B07B5AD78FDE8 /* token_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = token_test.cc; path = credentials/token_test.cc; sourceTree = ""; }; - A17F8CBAFA07CAE9FFBC8BC5 /* Pods_Firestore_Example_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A20BAA3D2F994384279727EC /* md5_testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = md5_testing.h; sourceTree = ""; }; A2E6F09AD1EE0A6A452E9A08 /* bloom_filter_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = bloom_filter_test.cc; sourceTree = ""; }; A366F6AE1A5A77548485C091 /* bundle.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = bundle.pb.cc; sourceTree = ""; }; A410E38FA5C3EB5AECDB6F1C /* inequality_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = inequality_test.cc; path = pipeline/inequality_test.cc; sourceTree = ""; }; A4192EB032E23129EF23605A /* field_behavior.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = field_behavior.pb.h; sourceTree = ""; }; - A47DF1B9E7CDA6F76A0BFF57 /* Pods-Firestore_Example_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS.debug.xcconfig"; sourceTree = ""; }; A5466E7809AD2871FFDE6C76 /* view_testing.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = view_testing.cc; sourceTree = ""; }; A5D9044B72061CAF284BC9E4 /* Validation_BloomFilterTest_MD5_50000_0001_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_50000_0001_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_50000_0001_bloom_filter_proto.json; sourceTree = ""; }; - A668C02CBF00BC56AEC81C2A /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig"; sourceTree = ""; }; A853C81A6A5A51C9D0389EDA /* bundle_loader_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = bundle_loader_test.cc; path = bundle/bundle_loader_test.cc; sourceTree = ""; }; AAED89D7690E194EF3BA1132 /* garbage_collection_spec_test.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; path = garbage_collection_spec_test.json; sourceTree = ""; }; AB323F9553050F4F6490F9FF /* pretty_printing_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = pretty_printing_test.cc; path = nanopb/pretty_printing_test.cc; sourceTree = ""; }; @@ -2290,9 +2289,8 @@ B9ED38DA914BDCD2E3A0714D /* aggregation_result.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = aggregation_result.pb.h; sourceTree = ""; }; BA02DA2FCD0001CFC6EB08DA /* filesystem_testing.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = filesystem_testing.cc; sourceTree = ""; }; BA4CBA48204C9E25B56993BC /* fields_array_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = fields_array_test.cc; path = nanopb/fields_array_test.cc; sourceTree = ""; }; - BB5A5E6DD07DA3EB7AD46CA7 /* Pods_Firestore_Example_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BC3C788D290A935C353CEAA1 /* writer_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = writer_test.cc; path = nanopb/writer_test.cc; sourceTree = ""; }; - BC758DA6CABF213979029A2B /* Pods_Firestore_Benchmarks_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Benchmarks_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BD030C308116480114144B89 /* Pods-Firestore_Example_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS.debug.xcconfig"; sourceTree = ""; }; BF76A8DA34B5B67B4DD74666 /* field_index_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = field_index_test.cc; sourceTree = ""; }; C0C7C8977C94F9F9AFA4DB00 /* local_store_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = local_store_test.h; sourceTree = ""; }; C7429071B33BDF80A7FA2F8A /* view_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = view_test.cc; sourceTree = ""; }; @@ -2303,25 +2301,24 @@ CB7B2D4691C380DE3EB59038 /* lru_garbage_collector_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = lru_garbage_collector_test.h; sourceTree = ""; }; CB852EE6E7D301545700BFD8 /* map_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = map_test.cc; path = expressions/map_test.cc; sourceTree = ""; }; CC572A9168BBEF7B83E4BBC5 /* view_snapshot_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = view_snapshot_test.cc; sourceTree = ""; }; + CC85FC848368E88FA264A1BE /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS.release.xcconfig"; sourceTree = ""; }; CCC9BD953F121B9E29F9AA42 /* user_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = user_test.cc; path = credentials/user_test.cc; sourceTree = ""; }; CD422AF3E4515FB8E9BE67A0 /* equals_tester.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = equals_tester.h; sourceTree = ""; }; CDC018C1D4CEC9B131449F98 /* expression_test_util.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = expression_test_util.h; sourceTree = ""; }; CE37875365497FFA8687B745 /* message_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = message_test.cc; path = nanopb/message_test.cc; sourceTree = ""; }; CF39535F2C41AB0006FA6C0E /* create_noop_connectivity_monitor.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = create_noop_connectivity_monitor.cc; sourceTree = ""; }; CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRTransactionOptionsTests.mm; sourceTree = ""; }; - CF46848D36D97041A7EF0554 /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS.release.xcconfig"; sourceTree = ""; }; D0A6E9136804A41CEC9D55D4 /* delayed_constructor_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = delayed_constructor_test.cc; sourceTree = ""; }; D22D4C211AC32E4F8B4883DA /* Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json; sourceTree = ""; }; D3CC3DC5338DCAF43A211155 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; D49E7AEE500651D25C5360C3 /* pipeline.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = pipeline.pb.cc; sourceTree = ""; }; D5B2593BCB52957D62F1C9D3 /* perf_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = perf_spec_test.json; sourceTree = ""; }; D5B25E7E7D6873CBA4571841 /* FIRNumericTransformTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRNumericTransformTests.mm; sourceTree = ""; }; - D6714D35B66361601CB3C749 /* Pods-Firestore_Tests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS.debug.xcconfig"; sourceTree = ""; }; D85AC18C55650ED230A71B82 /* FSTTestingHooks.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTTestingHooks.mm; sourceTree = ""; }; D872D754B8AD88E28AF28B28 /* aggregation_result.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = aggregation_result.pb.cc; sourceTree = ""; }; D8A6D52723B1BABE1B7B8D8F /* leveldb_overlay_migration_manager_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_overlay_migration_manager_test.cc; sourceTree = ""; }; + D8B9310A8C2FA2201E1261B4 /* Pods_Firestore_Tests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D8E530B27D5641B9C26A452C /* Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json; sourceTree = ""; }; - D9C9F60851E52197B30E0AF9 /* Pods_Firestore_IntegrationTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D9D94300B9C02F7069523C00 /* leveldb_snappy_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_snappy_test.cc; sourceTree = ""; }; DAFF0CF521E64AC30062958F /* Firestore_Example_macOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Firestore_Example_macOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; DAFF0CF721E64AC30062958F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; @@ -2332,7 +2329,6 @@ DAFF0D0021E64AC40062958F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; DAFF0D0221E64AC40062958F /* macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = ""; }; DB1F1E1B1ED15E8D042144B1 /* leveldb_query_engine_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_query_engine_test.cc; sourceTree = ""; }; - DB58B9A32136B962240C8716 /* Pods-Firestore_Example_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS.release.xcconfig"; sourceTree = ""; }; DB5A1E760451189DA36028B3 /* memory_index_manager_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_index_manager_test.cc; sourceTree = ""; }; DD12BC1DB2480886D2FB0005 /* settings_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = settings_test.cc; path = api/settings_test.cc; sourceTree = ""; }; DD520991DBDF5C11BBFAFE6D /* null_semantics_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = null_semantics_test.cc; path = pipeline/null_semantics_test.cc; sourceTree = ""; }; @@ -2344,12 +2340,16 @@ DE51B1981F0D48AC0013853F /* FSTSpecTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSTSpecTests.h; sourceTree = ""; }; DE51B19A1F0D48AC0013853F /* FSTSyncEngineTestDriver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSTSyncEngineTestDriver.h; sourceTree = ""; }; DE51B1A71F0D48AC0013853F /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + DE9C9075C63C66F01961750F /* Pods-Firestore_Tests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS.release.xcconfig"; sourceTree = ""; }; DF445D5201750281F1817387 /* document_overlay_cache_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = document_overlay_cache_test.h; sourceTree = ""; }; + DFB2CD94DF4A37DCC987E3CC /* Pods-Firestore_Example_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS.debug.xcconfig"; sourceTree = ""; }; E1459FA70B8FC18DE4B80D0D /* overlay_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = overlay_test.cc; sourceTree = ""; }; E2E39422953DE1D3C7B97E77 /* md5_testing.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = md5_testing.cc; sourceTree = ""; }; E3228F51DCDC2E90D5C58F97 /* ConditionalConformanceTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConditionalConformanceTests.swift; sourceTree = ""; }; E76F0CDF28E5FA62D21DE648 /* leveldb_target_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_target_cache_test.cc; sourceTree = ""; }; + E99993350B9F360190C6A886 /* Pods_Firestore_IntegrationTests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; EA10515F99A42D71DA2D2841 /* thread_safe_memoizer_testing_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = thread_safe_memoizer_testing_test.cc; sourceTree = ""; }; + EC00431536EFDDE0256357E2 /* Pods-Firestore_Tests_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS.debug.xcconfig"; sourceTree = ""; }; EEF23C7104A4D040C3A8CF9B /* string_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = string_test.cc; path = expressions/string_test.cc; sourceTree = ""; }; EF3A65472C66B9560041EE69 /* FIRVectorValueTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRVectorValueTests.mm; sourceTree = ""; }; EF6C285029E462A200A7D4F1 /* FIRAggregateTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRAggregateTests.mm; sourceTree = ""; }; @@ -2358,8 +2358,7 @@ EFF22EA92C5060A4009A369B /* VectorIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VectorIntegrationTests.swift; sourceTree = ""; }; F02F734F272C3C70D1307076 /* filter_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = filter_test.cc; sourceTree = ""; }; F119BDDF2F06B3C0883B8297 /* firebase_app_check_credentials_provider_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = firebase_app_check_credentials_provider_test.mm; path = credentials/firebase_app_check_credentials_provider_test.mm; sourceTree = ""; }; - F243090EDC079930C87D5F96 /* Pods-Firestore_Tests_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS.debug.xcconfig"; sourceTree = ""; }; - F339B5B848F79BBDB2133210 /* Pods-Firestore_Example_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS.release.xcconfig"; sourceTree = ""; }; + F1F1CCCF68677C413FEFB2BC /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Benchmarks_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS.debug.xcconfig"; sourceTree = ""; }; F3704E3BF509EE783D0B0F08 /* mirroring_semantics_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = mirroring_semantics_test.cc; path = expressions/mirroring_semantics_test.cc; sourceTree = ""; }; F51619F8CFF13B0CDD13EDC3 /* logical_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = logical_test.cc; path = expressions/logical_test.cc; sourceTree = ""; }; F51859B394D01C0C507282F1 /* filesystem_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = filesystem_test.cc; sourceTree = ""; }; @@ -2367,9 +2366,10 @@ F6DBD8EDF0074DD0079ECCE6 /* debug_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = debug_test.cc; path = expressions/debug_test.cc; sourceTree = ""; }; F7FC06E0A47D393DE1759AE1 /* bundle_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = bundle_cache_test.cc; sourceTree = ""; }; F8043813A5D16963EC02B182 /* local_serializer_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = local_serializer_test.cc; sourceTree = ""; }; + F8222AA70B3B1CAA6CF73DE0 /* Pods-Firestore_Tests_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS.release.xcconfig"; sourceTree = ""; }; F848C41C03A25C42AD5A4BC2 /* target_cache_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = target_cache_test.h; sourceTree = ""; }; F869D85E900E5AF6CD02E2FC /* firebase_auth_credentials_provider_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = firebase_auth_credentials_provider_test.mm; path = credentials/firebase_auth_credentials_provider_test.mm; sourceTree = ""; }; - FBEED3A3B940302D76B6113A /* Pods-Firestore_Tests_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS.release.xcconfig"; sourceTree = ""; }; + F9C6CD63A780B7E8F1EBF761 /* Pods_Firestore_Tests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FC44D934D4A52C790659C8D6 /* leveldb_globals_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_globals_cache_test.cc; sourceTree = ""; }; FF73B39D04D1760190E6B84A /* FIRQueryUnitTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRQueryUnitTests.mm; sourceTree = ""; }; FFCA39825D9678A03D1845D0 /* document_overlay_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = document_overlay_cache_test.cc; sourceTree = ""; }; @@ -2380,7 +2380,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9A13350EF5C115DF314BFE1D /* Pods_Firestore_Tests_macOS.framework in Frameworks */, + 9948EC749F74B2FA50E96845 /* Pods_Firestore_Tests_macOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2388,7 +2388,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 7A6BDBD2C373800BAA202526 /* Pods_Firestore_Example_tvOS.framework in Frameworks */, + 94EC0C2B013259594DA44983 /* Pods_Firestore_Example_tvOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2396,7 +2396,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 35EAE24071EAF2E69931B0F7 /* Pods_Firestore_Tests_tvOS.framework in Frameworks */, + B4321FCCCFBC787BF1109FC5 /* Pods_Firestore_Tests_tvOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2404,7 +2404,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C5F7739063B1515A8628B370 /* Pods_Firestore_IntegrationTests_tvOS.framework in Frameworks */, + BFFF80B66D9D8BDB91844575 /* Pods_Firestore_IntegrationTests_tvOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2412,7 +2412,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1DE9E7D3143F10C34A42639C /* Pods_Firestore_IntegrationTests_macOS.framework in Frameworks */, + 05A18C838432F611F21F1C53 /* Pods_Firestore_IntegrationTests_macOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2420,7 +2420,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5AFB773E190A8FDC6C2D3DB6 /* Pods_Firestore_Benchmarks_iOS.framework in Frameworks */, + 7E873E95A1C12646B7C22502 /* Pods_Firestore_Benchmarks_iOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2430,8 +2430,8 @@ files = ( 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, - 55B9A6ACDF95D356EA501D92 /* Pods_Firestore_Example_iOS.framework in Frameworks */, 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, + 3E81E93349135A3E814376F9 /* Pods_Firestore_Example_iOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2440,9 +2440,9 @@ buildActionMask = 2147483647; files = ( 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, - A4F2B68E7EFADB0EB443CFF8 /* Pods_Firestore_Tests_iOS.framework in Frameworks */, 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, + 352AA573D357554B9808D2CD /* Pods_Firestore_Tests_iOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2460,7 +2460,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 403B1ABF47F9FFE876F6DDCA /* Pods_Firestore_Example_macOS.framework in Frameworks */, + 2951C96256ECD27C2165907A /* Pods_Firestore_Example_macOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2469,9 +2469,9 @@ buildActionMask = 2147483647; files = ( DE03B2D61F2149D600A30B9C /* Foundation.framework in Frameworks */, - C9D01A1A30CD147F28493698 /* Pods_Firestore_IntegrationTests_iOS.framework in Frameworks */, DE03B2D51F2149D600A30B9C /* UIKit.framework in Frameworks */, DE03B2D41F2149D600A30B9C /* XCTest.framework in Frameworks */, + 175B5477F51147408A287F61 /* Pods_Firestore_IntegrationTests_iOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2882,18 +2882,18 @@ children = ( 6003F58F195388D20070C39A /* CoreGraphics.framework */, 6003F58D195388D20070C39A /* Foundation.framework */, - BC758DA6CABF213979029A2B /* Pods_Firestore_Benchmarks_iOS.framework */, - BB5A5E6DD07DA3EB7AD46CA7 /* Pods_Firestore_Example_iOS.framework */, - A17F8CBAFA07CAE9FFBC8BC5 /* Pods_Firestore_Example_macOS.framework */, - 9A7EE8E1466BA54F199B0991 /* Pods_Firestore_Example_tvOS.framework */, - D9C9F60851E52197B30E0AF9 /* Pods_Firestore_IntegrationTests_iOS.framework */, - 253A7A96FFAA2C8A8754D3CF /* Pods_Firestore_IntegrationTests_macOS.framework */, - 453332546740E27077C65FDC /* Pods_Firestore_IntegrationTests_tvOS.framework */, - 8294C2063C0096AE5E43F6DF /* Pods_Firestore_Tests_iOS.framework */, - 10F64BFFE86C4316F3F8AD95 /* Pods_Firestore_Tests_macOS.framework */, - 406BBAC409B5EB8531D366CA /* Pods_Firestore_Tests_tvOS.framework */, 6003F591195388D20070C39A /* UIKit.framework */, 6003F5AF195388D20070C39A /* XCTest.framework */, + 29656CF5FBF6FA0230D7B6EA /* Pods_Firestore_Benchmarks_iOS.framework */, + 82FFAF9DBBA0F7ABD2A0AEAD /* Pods_Firestore_Example_iOS.framework */, + 8E41D518EC9B6079252C063D /* Pods_Firestore_Example_macOS.framework */, + 56DFA1A5F0D4F7CE4F014158 /* Pods_Firestore_Example_tvOS.framework */, + 4DD0B43814F694A7004F307F /* Pods_Firestore_IntegrationTests_iOS.framework */, + 949E444D7EAA5BE81BBE5E5E /* Pods_Firestore_IntegrationTests_macOS.framework */, + E99993350B9F360190C6A886 /* Pods_Firestore_IntegrationTests_tvOS.framework */, + F9C6CD63A780B7E8F1EBF761 /* Pods_Firestore_Tests_iOS.framework */, + 2696F7160BC0525999F33F85 /* Pods_Firestore_Tests_macOS.framework */, + D8B9310A8C2FA2201E1261B4 /* Pods_Firestore_Tests_tvOS.framework */, ); name = Frameworks; sourceTree = ""; @@ -3036,26 +3036,26 @@ 67DC68172636F7FE04B766D4 /* Pods */ = { isa = PBXGroup; children = ( - 25191D04F1D477571A7D3740 /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */, - 03BD47161789F26754D3B958 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */, - 81DFB7DE556603F7FDEDCA84 /* Pods-Firestore_Example_iOS.debug.xcconfig */, - DB58B9A32136B962240C8716 /* Pods-Firestore_Example_iOS.release.xcconfig */, - 99DD94DE29B06444E0C7CBAC /* Pods-Firestore_Example_macOS.debug.xcconfig */, - 88B7F25F26338EB9C03AE440 /* Pods-Firestore_Example_macOS.release.xcconfig */, - A47DF1B9E7CDA6F76A0BFF57 /* Pods-Firestore_Example_tvOS.debug.xcconfig */, - F339B5B848F79BBDB2133210 /* Pods-Firestore_Example_tvOS.release.xcconfig */, - 708BC2920AEF83DC6630887E /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */, - 62CF8E2E7611B285B46228FE /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */, - 5C767F7D43A603B557327513 /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */, - 4B2C0786117A4C34F4CD0C6A /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */, - A668C02CBF00BC56AEC81C2A /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */, - CF46848D36D97041A7EF0554 /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */, - D6714D35B66361601CB3C749 /* Pods-Firestore_Tests_iOS.debug.xcconfig */, - 5BAD4FE9D876483DDAD34D96 /* Pods-Firestore_Tests_iOS.release.xcconfig */, - 29749DC3DADA38CAD1EB9AC4 /* Pods-Firestore_Tests_macOS.debug.xcconfig */, - 708CD87D3C1E72E63229AB09 /* Pods-Firestore_Tests_macOS.release.xcconfig */, - F243090EDC079930C87D5F96 /* Pods-Firestore_Tests_tvOS.debug.xcconfig */, - FBEED3A3B940302D76B6113A /* Pods-Firestore_Tests_tvOS.release.xcconfig */, + F1F1CCCF68677C413FEFB2BC /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */, + 04F95FB0B1123006B5DA8153 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */, + BD030C308116480114144B89 /* Pods-Firestore_Example_iOS.debug.xcconfig */, + 20C55A10362C9BDE9FB8C5E1 /* Pods-Firestore_Example_iOS.release.xcconfig */, + 6ABFEF8FB2361EEE737CB120 /* Pods-Firestore_Example_macOS.debug.xcconfig */, + 6CA462CE027855D254A69006 /* Pods-Firestore_Example_macOS.release.xcconfig */, + DFB2CD94DF4A37DCC987E3CC /* Pods-Firestore_Example_tvOS.debug.xcconfig */, + 459864A45E38975067B09B19 /* Pods-Firestore_Example_tvOS.release.xcconfig */, + 831CE94805EAC3F88B9019DA /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */, + 8DB38D2B14D3955ACA3F3952 /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */, + 9DE6467395E0973563A0BF9D /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */, + 319C19479B01F7DEEAD9774A /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */, + 765CEDF282B8255A337CEF80 /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */, + CC85FC848368E88FA264A1BE /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */, + 4BB169579995C73A8BF4D981 /* Pods-Firestore_Tests_iOS.debug.xcconfig */, + DE9C9075C63C66F01961750F /* Pods-Firestore_Tests_iOS.release.xcconfig */, + 4EAA1E2AC6B9AD4D3876C451 /* Pods-Firestore_Tests_macOS.debug.xcconfig */, + 5DC11E3981B81DDFF8A4453B /* Pods-Firestore_Tests_macOS.release.xcconfig */, + EC00431536EFDDE0256357E2 /* Pods-Firestore_Tests_tvOS.debug.xcconfig */, + F8222AA70B3B1CAA6CF73DE0 /* Pods-Firestore_Tests_tvOS.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -3381,11 +3381,11 @@ isa = PBXNativeTarget; buildConfigurationList = 544AB19B2248072200F851E6 /* Build configuration list for PBXNativeTarget "Firestore_Tests_macOS" */; buildPhases = ( - E26B0DC5040F20435672F64C /* [CP] Check Pods Manifest.lock */, + D0E2864849F7821EA1766350 /* [CP] Check Pods Manifest.lock */, 544AB18E2248072200F851E6 /* Sources */, 544AB18F2248072200F851E6 /* Frameworks */, 544AB1902248072200F851E6 /* Resources */, - 29735D999BBE6CED7C29C5DF /* [CP] Embed Pods Frameworks */, + 470F142676C51630881DE722 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3401,11 +3401,11 @@ isa = PBXNativeTarget; buildConfigurationList = 54AA33A1224BF936006CE580 /* Build configuration list for PBXNativeTarget "Firestore_Example_tvOS" */; buildPhases = ( - DFBD1CEC9B09E33A689F1393 /* [CP] Check Pods Manifest.lock */, + 9924014786EA7DE18926B94C /* [CP] Check Pods Manifest.lock */, 54AA338B224BF935006CE580 /* Sources */, 54AA338C224BF935006CE580 /* Frameworks */, 54AA338D224BF935006CE580 /* Resources */, - FD0B05136491959E422B3460 /* [CP] Embed Pods Frameworks */, + BFA27F7A0A2F3791CC6AD5F3 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3420,11 +3420,11 @@ isa = PBXNativeTarget; buildConfigurationList = 54AA33AF224BFE0A006CE580 /* Build configuration list for PBXNativeTarget "Firestore_Tests_tvOS" */; buildPhases = ( - BFF603779861F33DCFC72B8F /* [CP] Check Pods Manifest.lock */, + 4BFF87BC6397E978B275C6A8 /* [CP] Check Pods Manifest.lock */, 54AA33A2224BFE09006CE580 /* Sources */, 54AA33A3224BFE09006CE580 /* Frameworks */, 54AA33A4224BFE09006CE580 /* Resources */, - F5D323260BD8A5BAE37A880F /* [CP] Embed Pods Frameworks */, + C28155D3E0ED2F6C48249B5F /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3440,11 +3440,11 @@ isa = PBXNativeTarget; buildConfigurationList = 54AA33BB224C0035006CE580 /* Build configuration list for PBXNativeTarget "Firestore_IntegrationTests_tvOS" */; buildPhases = ( - E066E2665F94031B95DE2332 /* [CP] Check Pods Manifest.lock */, + C85CCD6E92EE34EA8E132CCC /* [CP] Check Pods Manifest.lock */, 54AA33B0224C0035006CE580 /* Sources */, 54AA33B1224C0035006CE580 /* Frameworks */, 54AA33B2224C0035006CE580 /* Resources */, - 2EFDF915A99FF34B2A592A3B /* [CP] Embed Pods Frameworks */, + 4EFCC40FAD4523014466B872 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3460,11 +3460,11 @@ isa = PBXNativeTarget; buildConfigurationList = 54B8E4B3224BDC4100930F18 /* Build configuration list for PBXNativeTarget "Firestore_IntegrationTests_macOS" */; buildPhases = ( - AC3A1FAA5AB14C1518AB82C3 /* [CP] Check Pods Manifest.lock */, + 8910A34006286584E91CC6DC /* [CP] Check Pods Manifest.lock */, 54B8E4A6224BDC4100930F18 /* Sources */, 54B8E4A7224BDC4100930F18 /* Frameworks */, 54B8E4A8224BDC4100930F18 /* Resources */, - 18BBDA6B794445C4E4B1A856 /* [CP] Embed Pods Frameworks */, + 633674F5147FBB8C1FD5FEDD /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3480,11 +3480,11 @@ isa = PBXNativeTarget; buildConfigurationList = 5CAE132020FFFED600BE9A4A /* Build configuration list for PBXNativeTarget "Firestore_Benchmarks_iOS" */; buildPhases = ( - 1F402F6D1128E05262C78C03 /* [CP] Check Pods Manifest.lock */, + C68DD37C165D7B574ECBB922 /* [CP] Check Pods Manifest.lock */, 5CAE131520FFFED600BE9A4A /* Sources */, 5CAE131620FFFED600BE9A4A /* Frameworks */, 5CAE131720FFFED600BE9A4A /* Resources */, - E45EB880BFD8443E5C77D66D /* [CP] Embed Pods Frameworks */, + B95E0392E921938AC60FCF25 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3500,11 +3500,11 @@ isa = PBXNativeTarget; buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "Firestore_Example_iOS" */; buildPhases = ( - 9C2E237472C81661EDBB7A11 /* [CP] Check Pods Manifest.lock */, + D597DC0C7CBDC9CBBF450EF9 /* [CP] Check Pods Manifest.lock */, 6003F586195388D20070C39A /* Sources */, 6003F587195388D20070C39A /* Frameworks */, 6003F588195388D20070C39A /* Resources */, - B6989D24F1918E3AC09BBBFF /* [CP] Embed Pods Frameworks */, + CAFA3F6E97C2D5C7FB66B9A7 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3519,11 +3519,11 @@ isa = PBXNativeTarget; buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Firestore_Tests_iOS" */; buildPhases = ( - 9B943CABAC29C06A6F202CDD /* [CP] Check Pods Manifest.lock */, + 7F5E4B9C83AA91EFE162BF97 /* [CP] Check Pods Manifest.lock */, 6003F5AA195388D20070C39A /* Sources */, 6003F5AB195388D20070C39A /* Frameworks */, 6003F5AC195388D20070C39A /* Resources */, - F6F0E43275E106B383A8A88E /* [CP] Embed Pods Frameworks */, + 3E49BD3598B1B6454C94341C /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3558,11 +3558,11 @@ isa = PBXNativeTarget; buildConfigurationList = DAFF0D0521E64AC40062958F /* Build configuration list for PBXNativeTarget "Firestore_Example_macOS" */; buildPhases = ( - 42C55F231E24330A93F24CD3 /* [CP] Check Pods Manifest.lock */, + 11729AF0AA6C8C2719E12B93 /* [CP] Check Pods Manifest.lock */, DAFF0CF121E64AC30062958F /* Sources */, DAFF0CF221E64AC30062958F /* Frameworks */, DAFF0CF321E64AC30062958F /* Resources */, - D7951351EFF77D9101090DC4 /* [CP] Embed Pods Frameworks */, + 4AD644A1CEE1248C527E892A /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3577,11 +3577,11 @@ isa = PBXNativeTarget; buildConfigurationList = DE03B2E61F2149D600A30B9C /* Build configuration list for PBXNativeTarget "Firestore_IntegrationTests_iOS" */; buildPhases = ( - 6F2714650E4142FA1E70FA2E /* [CP] Check Pods Manifest.lock */, + CBADFCA235F8428F57C4F3E4 /* [CP] Check Pods Manifest.lock */, DE03B2981F2149D600A30B9C /* Sources */, DE03B2D31F2149D600A30B9C /* Frameworks */, DE03B2D81F2149D600A30B9C /* Resources */, - 33D2EF75F253D4D5C758AE5F /* [CP] Embed Pods Frameworks */, + 23F727CA498241B895EF8577 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -4032,44 +4032,44 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 18BBDA6B794445C4E4B1A856 /* [CP] Embed Pods Frameworks */ = { + 11729AF0AA6C8C2719E12B93 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_macOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 1F402F6D1128E05262C78C03 /* [CP] Check Pods Manifest.lock */ = { + 23F727CA498241B895EF8577 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Benchmarks_iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 29735D999BBE6CED7C29C5DF /* [CP] Embed Pods Frameworks */ = { + 3E49BD3598B1B6454C94341C /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4081,10 +4081,10 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 2EFDF915A99FF34B2A592A3B /* [CP] Embed Pods Frameworks */ = { + 470F142676C51630881DE722 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4096,10 +4096,10 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 33D2EF75F253D4D5C758AE5F /* [CP] Embed Pods Frameworks */ = { + 4AD644A1CEE1248C527E892A /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4111,10 +4111,10 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 42C55F231E24330A93F24CD3 /* [CP] Check Pods Manifest.lock */ = { + 4BFF87BC6397E978B275C6A8 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4129,75 +4129,61 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_macOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_tvOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 6E622C7A20F52C8300B7E93A /* Run Script */ = { + 4EFCC40FAD4523014466B872 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; - buildActionMask = 12; + buildActionMask = 2147483647; files = ( ); inputPaths = ( - "$(SRCROOT)/FuzzTests/FuzzingResources/Serializer/Corpus/TextProtos", ); - name = "Run Script"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(TARGET_BUILD_DIR)/FuzzTestsCorpus", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/FuzzTests/FuzzingResources/Serializer/Corpus/ConvertTextToBinary.sh\""; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 6F2714650E4142FA1E70FA2E /* [CP] Check Pods Manifest.lock */ = { + 633674F5147FBB8C1FD5FEDD /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_IntegrationTests_iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 9B943CABAC29C06A6F202CDD /* [CP] Check Pods Manifest.lock */ = { + 6E622C7A20F52C8300B7E93A /* Run Script */ = { isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; + buildActionMask = 12; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( + "$(SRCROOT)/FuzzTests/FuzzingResources/Serializer/Corpus/TextProtos", ); + name = "Run Script"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_iOS-checkManifestLockResult.txt", + "$(TARGET_BUILD_DIR)/FuzzTestsCorpus", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${SRCROOT}/FuzzTests/FuzzingResources/Serializer/Corpus/ConvertTextToBinary.sh\""; showEnvVarsInLog = 0; }; - 9C2E237472C81661EDBB7A11 /* [CP] Check Pods Manifest.lock */ = { + 7F5E4B9C83AA91EFE162BF97 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4212,14 +4198,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_iOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - AC3A1FAA5AB14C1518AB82C3 /* [CP] Check Pods Manifest.lock */ = { + 8910A34006286584E91CC6DC /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4241,44 +4227,44 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - B6989D24F1918E3AC09BBBFF /* [CP] Embed Pods Frameworks */ = { + 9924014786EA7DE18926B94C /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_tvOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - BFF603779861F33DCFC72B8F /* [CP] Check Pods Manifest.lock */ = { + B95E0392E921938AC60FCF25 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_tvOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - D7951351EFF77D9101090DC4 /* [CP] Embed Pods Frameworks */ = { + BFA27F7A0A2F3791CC6AD5F3 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4290,32 +4276,25 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - DFBD1CEC9B09E33A689F1393 /* [CP] Check Pods Manifest.lock */ = { + C28155D3E0ED2F6C48249B5F /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_tvOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - E066E2665F94031B95DE2332 /* [CP] Check Pods Manifest.lock */ = { + C68DD37C165D7B574ECBB922 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4330,14 +4309,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_IntegrationTests_tvOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Firestore_Benchmarks_iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - E26B0DC5040F20435672F64C /* [CP] Check Pods Manifest.lock */ = { + C85CCD6E92EE34EA8E132CCC /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4352,14 +4331,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_macOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Firestore_IntegrationTests_tvOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - E45EB880BFD8443E5C77D66D /* [CP] Embed Pods Frameworks */ = { + CAFA3F6E97C2D5C7FB66B9A7 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4371,52 +4350,73 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - F5D323260BD8A5BAE37A880F /* [CP] Embed Pods Frameworks */ = { + CBADFCA235F8428F57C4F3E4 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Firestore_IntegrationTests_iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - F6F0E43275E106B383A8A88E /* [CP] Embed Pods Frameworks */ = { + D0E2864849F7821EA1766350 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_macOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - FD0B05136491959E422B3460 /* [CP] Embed Pods Frameworks */ = { + D597DC0C7CBDC9CBBF450EF9 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -6137,7 +6137,7 @@ /* Begin XCBuildConfiguration section */ 544AB1992248072200F851E6 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 29749DC3DADA38CAD1EB9AC4 /* Pods-Firestore_Tests_macOS.debug.xcconfig */; + baseConfigurationReference = 4EAA1E2AC6B9AD4D3876C451 /* Pods-Firestore_Tests_macOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6161,7 +6161,7 @@ }; 544AB19A2248072200F851E6 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 708CD87D3C1E72E63229AB09 /* Pods-Firestore_Tests_macOS.release.xcconfig */; + baseConfigurationReference = 5DC11E3981B81DDFF8A4453B /* Pods-Firestore_Tests_macOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6187,7 +6187,7 @@ }; 54AA339F224BF936006CE580 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A47DF1B9E7CDA6F76A0BFF57 /* Pods-Firestore_Example_tvOS.debug.xcconfig */; + baseConfigurationReference = DFB2CD94DF4A37DCC987E3CC /* Pods-Firestore_Example_tvOS.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; @@ -6210,7 +6210,7 @@ }; 54AA33A0224BF936006CE580 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F339B5B848F79BBDB2133210 /* Pods-Firestore_Example_tvOS.release.xcconfig */; + baseConfigurationReference = 459864A45E38975067B09B19 /* Pods-Firestore_Example_tvOS.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; @@ -6234,7 +6234,7 @@ }; 54AA33AD224BFE0A006CE580 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F243090EDC079930C87D5F96 /* Pods-Firestore_Tests_tvOS.debug.xcconfig */; + baseConfigurationReference = EC00431536EFDDE0256357E2 /* Pods-Firestore_Tests_tvOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6256,7 +6256,7 @@ }; 54AA33AE224BFE0A006CE580 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FBEED3A3B940302D76B6113A /* Pods-Firestore_Tests_tvOS.release.xcconfig */; + baseConfigurationReference = F8222AA70B3B1CAA6CF73DE0 /* Pods-Firestore_Tests_tvOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6279,7 +6279,7 @@ }; 54AA33BC224C0035006CE580 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A668C02CBF00BC56AEC81C2A /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */; + baseConfigurationReference = 765CEDF282B8255A337CEF80 /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6301,7 +6301,7 @@ }; 54AA33BD224C0035006CE580 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CF46848D36D97041A7EF0554 /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */; + baseConfigurationReference = CC85FC848368E88FA264A1BE /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6324,7 +6324,7 @@ }; 54B8E4B1224BDC4100930F18 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5C767F7D43A603B557327513 /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */; + baseConfigurationReference = 9DE6467395E0973563A0BF9D /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6348,7 +6348,7 @@ }; 54B8E4B2224BDC4100930F18 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4B2C0786117A4C34F4CD0C6A /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */; + baseConfigurationReference = 319C19479B01F7DEEAD9774A /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6373,7 +6373,7 @@ }; 5CAE132120FFFED600BE9A4A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 25191D04F1D477571A7D3740 /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */; + baseConfigurationReference = F1F1CCCF68677C413FEFB2BC /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; @@ -6387,7 +6387,7 @@ }; 5CAE132220FFFED600BE9A4A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 03BD47161789F26754D3B958 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */; + baseConfigurationReference = 04F95FB0B1123006B5DA8153 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; @@ -6510,7 +6510,7 @@ }; 6003F5C0195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 81DFB7DE556603F7FDEDCA84 /* Pods-Firestore_Example_iOS.debug.xcconfig */; + baseConfigurationReference = BD030C308116480114144B89 /* Pods-Firestore_Example_iOS.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -6532,7 +6532,7 @@ }; 6003F5C1195388D20070C39A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DB58B9A32136B962240C8716 /* Pods-Firestore_Example_iOS.release.xcconfig */; + baseConfigurationReference = 20C55A10362C9BDE9FB8C5E1 /* Pods-Firestore_Example_iOS.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -6554,7 +6554,7 @@ }; 6003F5C3195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D6714D35B66361601CB3C749 /* Pods-Firestore_Tests_iOS.debug.xcconfig */; + baseConfigurationReference = 4BB169579995C73A8BF4D981 /* Pods-Firestore_Tests_iOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; @@ -6615,7 +6615,7 @@ }; 6003F5C4195388D20070C39A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5BAD4FE9D876483DDAD34D96 /* Pods-Firestore_Tests_iOS.release.xcconfig */; + baseConfigurationReference = DE9C9075C63C66F01961750F /* Pods-Firestore_Tests_iOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; @@ -6704,7 +6704,7 @@ }; DAFF0D0321E64AC40062958F /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 99DD94DE29B06444E0C7CBAC /* Pods-Firestore_Example_macOS.debug.xcconfig */; + baseConfigurationReference = 6ABFEF8FB2361EEE737CB120 /* Pods-Firestore_Example_macOS.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; @@ -6741,7 +6741,7 @@ }; DAFF0D0421E64AC40062958F /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 88B7F25F26338EB9C03AE440 /* Pods-Firestore_Example_macOS.release.xcconfig */; + baseConfigurationReference = 6CA462CE027855D254A69006 /* Pods-Firestore_Example_macOS.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; @@ -6779,7 +6779,7 @@ }; DE03B2E71F2149D600A30B9C /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 708BC2920AEF83DC6630887E /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */; + baseConfigurationReference = 831CE94805EAC3F88B9019DA /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; @@ -6804,7 +6804,7 @@ }; DE03B2E81F2149D600A30B9C /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 62CF8E2E7611B285B46228FE /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */; + baseConfigurationReference = 8DB38D2B14D3955ACA3F3952 /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; diff --git a/Firestore/core/src/api/expressions.cc b/Firestore/core/src/api/expressions.cc index 1ec99c287b1..8fcb86ec81a 100644 --- a/Firestore/core/src/api/expressions.cc +++ b/Firestore/core/src/api/expressions.cc @@ -19,7 +19,7 @@ #include #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/nanopb/nanopb_util.h" diff --git a/Firestore/core/src/api/stages.cc b/Firestore/core/src/api/stages.cc index 1a33958b8cb..5a9eab28687 100644 --- a/Firestore/core/src/api/stages.cc +++ b/Firestore/core/src/api/stages.cc @@ -25,7 +25,7 @@ #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" #include "Firestore/core/src/api/pipeline.h" -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" #include "Firestore/core/src/model/document_key.h" #include "Firestore/core/src/model/mutable_document.h" #include "Firestore/core/src/model/resource_path.h" diff --git a/Firestore/core/src/core/pipeline/aggregates.cc b/Firestore/core/src/core/pipeline/aggregates_evaluation.cc similarity index 97% rename from Firestore/core/src/core/pipeline/aggregates.cc rename to Firestore/core/src/core/pipeline/aggregates_evaluation.cc index 176763fd4ef..2e0bc1d29ab 100644 --- a/Firestore/core/src/core/pipeline/aggregates.cc +++ b/Firestore/core/src/core/pipeline/aggregates_evaluation.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/aggregates.h" +#include "Firestore/core/src/core/pipeline/aggregates_evaluation.h" #include diff --git a/Firestore/core/src/core/pipeline/aggregates.h b/Firestore/core/src/core/pipeline/aggregates_evaluation.h similarity index 84% rename from Firestore/core/src/core/pipeline/aggregates.h rename to Firestore/core/src/core/pipeline/aggregates_evaluation.h index f4de6bad9e9..933c53f4e74 100644 --- a/Firestore/core/src/core/pipeline/aggregates.h +++ b/Firestore/core/src/core/pipeline/aggregates_evaluation.h @@ -14,11 +14,11 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_H_ +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_EVALUATION_H_ #include -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { @@ -54,4 +54,4 @@ class CoreMinimum : public EvaluableExpr { } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_H_ +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_EVALUATION_H_ diff --git a/Firestore/core/src/core/pipeline/evaluation/arithmetic.h b/Firestore/core/src/core/pipeline/evaluation/arithmetic.h index 6d73f398e4f..53640181584 100644 --- a/Firestore/core/src/core/pipeline/evaluation/arithmetic.h +++ b/Firestore/core/src/core/pipeline/evaluation/arithmetic.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARITHMETIC_H_ #include -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/array.h b/Firestore/core/src/core/pipeline/evaluation/array.h index 4506635b282..397b54a5097 100644 --- a/Firestore/core/src/core/pipeline/evaluation/array.h +++ b/Firestore/core/src/core/pipeline/evaluation/array.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARRAY_H_ #include -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/comparison.h b/Firestore/core/src/core/pipeline/evaluation/comparison.h index 7404f4d38ce..23d6ac8e512 100644 --- a/Firestore/core/src/core/pipeline/evaluation/comparison.h +++ b/Firestore/core/src/core/pipeline/evaluation/comparison.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_COMPARISON_H_ #include -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/logical.h b/Firestore/core/src/core/pipeline/evaluation/logical.h index 6aa637ab2ab..597accca9c8 100644 --- a/Firestore/core/src/core/pipeline/evaluation/logical.h +++ b/Firestore/core/src/core/pipeline/evaluation/logical.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_LOGICAL_H_ #include -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/map.h b/Firestore/core/src/core/pipeline/evaluation/map.h index 2d615cdf9a3..4946f2cf6f5 100644 --- a/Firestore/core/src/core/pipeline/evaluation/map.h +++ b/Firestore/core/src/core/pipeline/evaluation/map.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_MAP_H_ #include -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/string.h b/Firestore/core/src/core/pipeline/evaluation/string.h index 9f610cad486..8c7cd1b78ee 100644 --- a/Firestore/core/src/core/pipeline/evaluation/string.h +++ b/Firestore/core/src/core/pipeline/evaluation/string.h @@ -19,7 +19,7 @@ #include #include -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/timestamp.h b/Firestore/core/src/core/pipeline/evaluation/timestamp.h index 859d63efb22..e5561152128 100644 --- a/Firestore/core/src/core/pipeline/evaluation/timestamp.h +++ b/Firestore/core/src/core/pipeline/evaluation/timestamp.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TIMESTAMP_H_ #include -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/type.h b/Firestore/core/src/core/pipeline/evaluation/type.h index e5928ba7468..a16635e1f18 100644 --- a/Firestore/core/src/core/pipeline/evaluation/type.h +++ b/Firestore/core/src/core/pipeline/evaluation/type.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TYPE_H_ #include -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/expression.cc b/Firestore/core/src/core/pipeline/expression_evaluation.cc similarity index 98% rename from Firestore/core/src/core/pipeline/expression.cc rename to Firestore/core/src/core/pipeline/expression_evaluation.cc index e3085a57ab7..ebe786fb409 100644 --- a/Firestore/core/src/core/pipeline/expression.cc +++ b/Firestore/core/src/core/pipeline/expression_evaluation.cc @@ -14,12 +14,12 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" #include #include // For std::move -#include "Firestore/core/src/core/pipeline/aggregates.h" +#include "Firestore/core/src/core/pipeline/aggregates_evaluation.h" #include "Firestore/core/src/core/pipeline/evaluation/arithmetic.h" #include "Firestore/core/src/core/pipeline/evaluation/array.h" #include "Firestore/core/src/core/pipeline/evaluation/comparison.h" diff --git a/Firestore/core/src/core/pipeline/expression.h b/Firestore/core/src/core/pipeline/expression_evaluation.h similarity index 95% rename from Firestore/core/src/core/pipeline/expression.h rename to Firestore/core/src/core/pipeline/expression_evaluation.h index 759d33b3876..fa44060c3bb 100644 --- a/Firestore/core/src/core/pipeline/expression.h +++ b/Firestore/core/src/core/pipeline/expression_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_H_ +#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_EVALUATION_H_ #include #include @@ -152,4 +152,4 @@ std::unique_ptr FunctionToEvaluable( } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_H_ +#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_EVALUATION_H_ diff --git a/Firestore/core/src/core/pipeline_util.cc b/Firestore/core/src/core/pipeline_util.cc index 9ed35af614d..c9db008f9b0 100644 --- a/Firestore/core/src/core/pipeline_util.cc +++ b/Firestore/core/src/core/pipeline_util.cc @@ -26,7 +26,7 @@ #include "Firestore/core/src/api/realtime_pipeline.h" #include "Firestore/core/src/api/stages.h" #include "Firestore/core/src/core/bound.h" -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" #include "Firestore/core/src/core/pipeline_run.h" #include "Firestore/core/src/core/query.h" #include "Firestore/core/src/model/document_set.h" diff --git a/Firestore/core/test/unit/core/expressions/arithmetic_test.cc b/Firestore/core/test/unit/core/expressions/arithmetic_test.cc index af825cc3eb3..4465236835b 100644 --- a/Firestore/core/test/unit/core/expressions/arithmetic_test.cc +++ b/Firestore/core/test/unit/core/expressions/arithmetic_test.cc @@ -17,7 +17,7 @@ #include #include -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" #include "Firestore/core/test/unit/testutil/expression_test_util.h" #include "Firestore/core/test/unit/testutil/testutil.h" #include "gmock/gmock.h" diff --git a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc index 2b04e4c94b1..975b0c4a892 100644 --- a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc +++ b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc @@ -21,7 +21,7 @@ #include #include "Firestore/core/src/api/expressions.h" -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" #include "Firestore/core/src/model/field_path.h" #include "Firestore/core/src/util/string_format.h" #include "Firestore/core/test/unit/testutil/expression_test_util.h" diff --git a/Firestore/core/test/unit/testutil/expression_test_util.h b/Firestore/core/test/unit/testutil/expression_test_util.h index c91c987c92d..fe4568d56b9 100644 --- a/Firestore/core/test/unit/testutil/expression_test_util.h +++ b/Firestore/core/test/unit/testutil/expression_test_util.h @@ -30,7 +30,7 @@ #include "Firestore/core/include/firebase/firestore/timestamp.h" #include "Firestore/core/src/api/expressions.h" #include "Firestore/core/src/api/stages.h" -#include "Firestore/core/src/core/pipeline/aggregates.h" +#include "Firestore/core/src/core/pipeline/aggregates_evaluation.h" #include "Firestore/core/src/core/pipeline/evaluation/arithmetic.h" #include "Firestore/core/src/core/pipeline/evaluation/array.h" #include "Firestore/core/src/core/pipeline/evaluation/comparison.h" @@ -39,7 +39,7 @@ #include "Firestore/core/src/core/pipeline/evaluation/string.h" #include "Firestore/core/src/core/pipeline/evaluation/timestamp.h" #include "Firestore/core/src/core/pipeline/evaluation/type.h" -#include "Firestore/core/src/core/pipeline/expression.h" +#include "Firestore/core/src/core/pipeline/expression_evaluation.h" #include "Firestore/core/src/model/database_id.h" #include "Firestore/core/src/model/document_key.h" #include "Firestore/core/src/model/mutable_document.h" From 036960e58fba4178927842433438e2353fdea5e9 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Tue, 2 Dec 2025 11:42:03 -0500 Subject: [PATCH 32/36] fix cocoapods build --- .../Firestore.xcodeproj/project.pbxproj | 432 +++++++++--------- Firestore/core/CMakeLists.txt | 42 +- Firestore/core/src/api/expressions.cc | 2 +- Firestore/core/src/api/stages.cc | 2 +- Firestore/core/src/core/pipeline_util.cc | 2 +- .../pipeline/aggregates_evaluation.cc | 2 +- .../pipeline/aggregates_evaluation.h | 2 +- .../arithmetic_evaluation.cc} | 4 +- .../arithmetic_evaluation.h} | 2 +- .../array.cc => pipeline/array_evaluation.cc} | 6 +- .../array.h => pipeline/array_evaluation.h} | 2 +- .../comparison_evaluation.cc} | 2 +- .../comparison_evaluation.h} | 2 +- .../pipeline/expression_evaluation.cc | 20 +- .../pipeline/expression_evaluation.h | 0 .../logical_evaluation.cc} | 2 +- .../logical_evaluation.h} | 2 +- .../map.cc => pipeline/map_evaluation.cc} | 2 +- .../map.h => pipeline/map_evaluation.h} | 2 +- .../string_evaluation.cc} | 4 +- .../string.h => pipeline/string_evaluation.h} | 2 +- .../timestamp_evaluation.cc} | 4 +- .../timestamp_evaluation.h} | 2 +- .../type.cc => pipeline/type_evaluation.cc} | 4 +- .../type.h => pipeline/type_evaluation.h} | 2 +- .../util.cc => pipeline/util_evaluation.cc} | 2 +- .../util.h => pipeline/util_evaluation.h} | 0 .../unit/core/expressions/arithmetic_test.cc | 2 +- .../expressions/mirroring_semantics_test.cc | 2 +- .../test/unit/testutil/expression_test_util.h | 20 +- 30 files changed, 288 insertions(+), 286 deletions(-) rename Firestore/core/src/{core => }/pipeline/aggregates_evaluation.cc (97%) rename Firestore/core/src/{core => }/pipeline/aggregates_evaluation.h (96%) rename Firestore/core/src/{core/pipeline/evaluation/arithmetic.cc => pipeline/arithmetic_evaluation.cc} (98%) rename Firestore/core/src/{core/pipeline/evaluation/arithmetic.h => pipeline/arithmetic_evaluation.h} (98%) rename Firestore/core/src/{core/pipeline/evaluation/array.cc => pipeline/array_evaluation.cc} (98%) rename Firestore/core/src/{core/pipeline/evaluation/array.h => pipeline/array_evaluation.h} (97%) rename Firestore/core/src/{core/pipeline/evaluation/comparison.cc => pipeline/comparison_evaluation.cc} (99%) rename Firestore/core/src/{core/pipeline/evaluation/comparison.h => pipeline/comparison_evaluation.h} (98%) rename Firestore/core/src/{core => }/pipeline/expression_evaluation.cc (94%) rename Firestore/core/src/{core => }/pipeline/expression_evaluation.h (100%) rename Firestore/core/src/{core/pipeline/evaluation/logical.cc => pipeline/logical_evaluation.cc} (99%) rename Firestore/core/src/{core/pipeline/evaluation/logical.h => pipeline/logical_evaluation.h} (98%) rename Firestore/core/src/{core/pipeline/evaluation/map.cc => pipeline/map_evaluation.cc} (97%) rename Firestore/core/src/{core/pipeline/evaluation/map.h => pipeline/map_evaluation.h} (95%) rename Firestore/core/src/{core/pipeline/evaluation/string.cc => pipeline/string_evaluation.cc} (99%) rename Firestore/core/src/{core/pipeline/evaluation/string.h => pipeline/string_evaluation.h} (98%) rename Firestore/core/src/{core/pipeline/evaluation/timestamp.cc => pipeline/timestamp_evaluation.cc} (98%) rename Firestore/core/src/{core/pipeline/evaluation/timestamp.h => pipeline/timestamp_evaluation.h} (98%) rename Firestore/core/src/{core/pipeline/evaluation/type.cc => pipeline/type_evaluation.cc} (97%) rename Firestore/core/src/{core/pipeline/evaluation/type.h => pipeline/type_evaluation.h} (97%) rename Firestore/core/src/{core/pipeline/evaluation/util.cc => pipeline/util_evaluation.cc} (97%) rename Firestore/core/src/{core/pipeline/evaluation/util.h => pipeline/util_evaluation.h} (100%) diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj index 70ac64a12db..2bd0e1c1b48 100644 --- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj +++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj @@ -47,7 +47,6 @@ 056542AD1D0F78E29E22EFA9 /* grpc_connection_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D9649021544D4F00EB9CFB /* grpc_connection_test.cc */; }; 0575F3004B896D94456A74CE /* status_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3CAA33F964042646FDDAF9F9 /* status_testing.cc */; }; 0595B5EBEB8F09952B72C883 /* logic_utils_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 28B45B2104E2DAFBBF86DBB7 /* logic_utils_test.cc */; }; - 05A18C838432F611F21F1C53 /* Pods_Firestore_IntegrationTests_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 949E444D7EAA5BE81BBE5E5E /* Pods_Firestore_IntegrationTests_macOS.framework */; }; 05D99904EA713414928DD920 /* query_listener_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7C3F995E040E9E9C5E8514BB /* query_listener_test.cc */; }; 062072B72773A055001655D7 /* AsyncAwaitIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 062072B62773A055001655D7 /* AsyncAwaitIntegrationTests.swift */; }; 062072B82773A055001655D7 /* AsyncAwaitIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 062072B62773A055001655D7 /* AsyncAwaitIntegrationTests.swift */; }; @@ -193,7 +192,6 @@ 16FF9073CA381CA43CA9BF29 /* FIRTransactionOptionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */; }; 1733601ECCEA33E730DEAF45 /* autoid_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54740A521FC913E500713A1A /* autoid_test.cc */; }; 17473086EBACB98CDC3CC65C /* view_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = C7429071B33BDF80A7FA2F8A /* view_test.cc */; }; - 175B5477F51147408A287F61 /* Pods_Firestore_IntegrationTests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DD0B43814F694A7004F307F /* Pods_Firestore_IntegrationTests_iOS.framework */; }; 17638F813B9B556FE7718C0C /* FIRQuerySnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04F202154AA00B64F25 /* FIRQuerySnapshotTests.mm */; }; 1792477DD2B3A1710BFD443F /* arithmetic_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 76EED4ED84056B623D92FE20 /* arithmetic_test.cc */; }; 17D5E2D389728F992297DA1F /* nested_properties_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8AC88AA2B929CFEC2656E37D /* nested_properties_test.cc */; }; @@ -329,7 +327,6 @@ 28E4B4A53A739AE2C9CF4159 /* FIRDocumentSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04B202154AA00B64F25 /* FIRDocumentSnapshotTests.mm */; }; 29243A4BBB2E2B1530A62C59 /* leveldb_transaction_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 88CF09277CFA45EE1273E3BA /* leveldb_transaction_test.cc */; }; 292BCC76AF1B916752764A8F /* leveldb_bundle_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8E9CD82E60893DDD7757B798 /* leveldb_bundle_cache_test.cc */; }; - 2951C96256ECD27C2165907A /* Pods_Firestore_Example_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E41D518EC9B6079252C063D /* Pods_Firestore_Example_macOS.framework */; }; 297DC2B3C1EB136D58F4BA9C /* byte_string_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5342CDDB137B4E93E2E85CCA /* byte_string_test.cc */; }; 298E0F8F6EB27AA36BA1CE76 /* FIRQueryUnitTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = FF73B39D04D1760190E6B84A /* FIRQueryUnitTests.mm */; }; 29954A3172DDFE5133D91E24 /* FSTLevelDBSpecTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E02C20213FFB00B64F25 /* FSTLevelDBSpecTests.mm */; }; @@ -404,7 +401,6 @@ 34B62A40BB56F9574B87B28B /* Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = D8E530B27D5641B9C26A452C /* Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json */; }; 34D69886DAD4A2029BFC5C63 /* precondition_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 549CCA5520A36E1F00BCEB75 /* precondition_test.cc */; }; 34E866DB52AAB7DB76B69A91 /* recovery_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 9C1AFCC9E616EC33D6E169CF /* recovery_spec_test.json */; }; - 352AA573D357554B9808D2CD /* Pods_Firestore_Tests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C6CD63A780B7E8F1EBF761 /* Pods_Firestore_Tests_iOS.framework */; }; 353E47129584B8DDF10138BD /* stream_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5B5414D28802BC76FDADABD6 /* stream_test.cc */; }; 35503DAC4FD0D765A2DE82A8 /* byte_stream_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 432C71959255C5DBDF522F52 /* byte_stream_test.cc */; }; 355A9171EF3F7AD44A9C60CB /* document_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB6B908320322E4D00CC290A /* document_test.cc */; }; @@ -412,6 +408,7 @@ 35DB74DFB2F174865BCCC264 /* leveldb_transaction_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 88CF09277CFA45EE1273E3BA /* leveldb_transaction_test.cc */; }; 35FEB53E165518C0DE155CB0 /* target_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 526D755F65AC676234F57125 /* target_test.cc */; }; 360EB1D691F9C19A21D0916F /* Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = D22D4C211AC32E4F8B4883DA /* Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json */; }; + 360FE605D54DC67861B90C80 /* Pods_Firestore_Tests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2231749BC05407EADF72CB29 /* Pods_Firestore_Tests_tvOS.framework */; }; 36999FC1F37930E8C9B6DA25 /* stream_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5B5414D28802BC76FDADABD6 /* stream_test.cc */; }; 36FD4CE79613D18BC783C55B /* string_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0EE5300F8233D14025EF0456 /* string_apple_test.mm */; }; 37286D731E432CB873354357 /* remote_event_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 584AE2C37A55B408541A6FF3 /* remote_event_test.cc */; }; @@ -450,6 +447,7 @@ 3B843E4C1F3A182900548890 /* remote_store_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 3B843E4A1F3930A400548890 /* remote_store_spec_test.json */; }; 3BA4EEA6153B3833F86B8104 /* writer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = BC3C788D290A935C353CEAA1 /* writer_test.cc */; }; 3BAFCABA851AE1865D904323 /* to_string_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B696858D2214B53900271095 /* to_string_test.cc */; }; + 3C391CFCA34C3C982A2879E2 /* Pods_Firestore_Tests_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEF63D0E366F0D07AFC234EC /* Pods_Firestore_Tests_macOS.framework */; }; 3C5D441E7D5C140F0FB14D91 /* bloom_filter_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = A2E6F09AD1EE0A6A452E9A08 /* bloom_filter_test.cc */; }; 3C63B6ED2E494437BBAD82D7 /* mirroring_semantics_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F3704E3BF509EE783D0B0F08 /* mirroring_semantics_test.cc */; }; 3C9DEC46FE7B3995A4EA629C /* memory_globals_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5C6DEA63FBDE19D841291723 /* memory_globals_cache_test.cc */; }; @@ -466,8 +464,8 @@ 3DFBA7413965F3E6F366E923 /* grpc_unary_call_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D964942163E63900EB9CFB /* grpc_unary_call_test.cc */; }; 3E101CE56C70F06BA2FDD56C /* Validation_BloomFilterTest_MD5_50000_1_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 3841925AA60E13A027F565E6 /* Validation_BloomFilterTest_MD5_50000_1_membership_test_result.json */; }; 3E38E4B33855DD6CF7526225 /* bundle_serializer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5C2A94EE24E60543F62CC35 /* bundle_serializer_test.cc */; }; + 3E4D0C53B43154D9FF0BC429 /* Pods_Firestore_Example_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CFD0175464350438D3A4F756 /* Pods_Firestore_Example_iOS.framework */; }; 3E5FD39FE7442883AB3CE1F2 /* Validation_BloomFilterTest_MD5_1_01_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 5C68EE4CB94C0DD6E333F546 /* Validation_BloomFilterTest_MD5_1_01_membership_test_result.json */; }; - 3E81E93349135A3E814376F9 /* Pods_Firestore_Example_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82FFAF9DBBA0F7ABD2A0AEAD /* Pods_Firestore_Example_iOS.framework */; }; 3F3C2DAD9F9326BF789B1C96 /* serializer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 61F72C5520BC48FD001A68CB /* serializer_test.cc */; }; 3F4B6300198FD78E7B19BC5A /* strerror_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 358C3B5FE573B1D60A4F7592 /* strerror_test.cc */; }; 3F6C9F8A993CF4B0CD51E7F0 /* lru_garbage_collector_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 277EAACC4DD7C21332E8496A /* lru_garbage_collector_test.cc */; }; @@ -534,6 +532,7 @@ 49C04B97AB282FFA82FD98CD /* latlng.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 618BBE9220B89AAC00B5BCE7 /* latlng.pb.cc */; }; 49C593017B5438B216FAF593 /* executor_libdispatch_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = B6FB4689208F9B9100554BA2 /* executor_libdispatch_test.mm */; }; 49DB9113178FAA52F14477B2 /* secure_random_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54740A531FC913E500713A1A /* secure_random_test.cc */; }; + 4A057F92BA79DAD4441B2380 /* Pods_Firestore_Example_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 788BBE9FBC7D1148D4BD6FC2 /* Pods_Firestore_Example_macOS.framework */; }; 4A22BE9429A75E8E0EC4BC14 /* grpc_streaming_reader_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D964922154AB8F00EB9CFB /* grpc_streaming_reader_test.cc */; }; 4A3FF3B16A39A5DC6B7EBA51 /* target.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 618BBE7D20B89AAC00B5BCE7 /* target.pb.cc */; }; 4A52CEB97A43F2F3ABC6A5C8 /* stream_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5B5414D28802BC76FDADABD6 /* stream_test.cc */; }; @@ -852,6 +851,7 @@ 65E67ED71688670CC6715800 /* load_bundle_task_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8F1A7B4158D9DD76EE4836BF /* load_bundle_task_test.cc */; }; 65FC1A102890C02EF1A65213 /* database_info_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB38D92E20235D22000A432D /* database_info_test.cc */; }; 660E99DEDA0A6FC1CCB200F9 /* FIRArrayTransformTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 73866A9F2082B069009BB4FF /* FIRArrayTransformTests.mm */; }; + 6613D37C71DD13DDEF7BCAD6 /* Pods_Firestore_IntegrationTests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66A73B45396313D614B1FC96 /* Pods_Firestore_IntegrationTests_tvOS.framework */; }; 662793139A36E5CFC935B949 /* task_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 899FC22684B0F7BEEAE13527 /* task_test.cc */; }; 662E94803D6FABE56F0D22C9 /* Validation_BloomFilterTest_MD5_500_01_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = DD990FD89C165F4064B4F608 /* Validation_BloomFilterTest_MD5_500_01_membership_test_result.json */; }; 66464C291396AF149AD908FD /* FIRDocumentReferenceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E049202154AA00B64F25 /* FIRDocumentReferenceTests.mm */; }; @@ -860,6 +860,7 @@ 66DFEA9E324797E6EA81CBA9 /* perf_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = D5B2593BCB52957D62F1C9D3 /* perf_spec_test.json */; }; 66FAB8EAC012A3822BD4D0C9 /* leveldb_util_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 332485C4DCC6BA0DBB5E31B7 /* leveldb_util_test.cc */; }; 6711E75A10EBA662341F5C9D /* leveldb_document_overlay_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AE89CFF09C6804573841397F /* leveldb_document_overlay_cache_test.cc */; }; + 6725C6773A3493E9221BEAC9 /* Pods_Firestore_IntegrationTests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2FE5F3EBFEC54350FFB9DDF /* Pods_Firestore_IntegrationTests_iOS.framework */; }; 677C833244550767B71DB1BA /* log_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54C2294E1FECABAE007D065B /* log_test.cc */; }; 67B8C34BDF0FFD7532D7BE4F /* Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 478DC75A0DCA6249A616DD30 /* Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json */; }; 67BC2B77C1CC47388E79D774 /* FIRSnapshotMetadataTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04D202154AA00B64F25 /* FIRSnapshotMetadataTests.mm */; }; @@ -903,6 +904,7 @@ 6E6B8B8D61426E20495D9DF5 /* memory_globals_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5C6DEA63FBDE19D841291723 /* memory_globals_cache_test.cc */; }; 6E7603BC1D8011A5D6F62072 /* credentials_provider_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2F4FA4576525144C5069A7A5 /* credentials_provider_test.cc */; }; 6E8302E021022309003E1EA3 /* FSTFuzzTestFieldPath.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6E8302DF21022309003E1EA3 /* FSTFuzzTestFieldPath.mm */; }; + 6E8432D9E9220A846C1FC4C4 /* Pods_Firestore_Benchmarks_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06362D2AFB59B3AB4DAE38CF /* Pods_Firestore_Benchmarks_iOS.framework */; }; 6E8CD8F545C8EDA84918977C /* index.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 395E8B07639E69290A929695 /* index.pb.cc */; }; 6EA1C48C20EB8D438893A949 /* Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 478DC75A0DCA6249A616DD30 /* Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json */; }; 6EA39FDE20FE820E008D461F /* FSTFuzzTestSerializer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6EA39FDD20FE820E008D461F /* FSTFuzzTestSerializer.mm */; }; @@ -1018,7 +1020,6 @@ 7DED491019248CE9B9E9EB50 /* FSTLevelDBSpecTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E02C20213FFB00B64F25 /* FSTLevelDBSpecTests.mm */; }; 7E1B1335B2EC566FB25B710C /* Validation_BloomFilterTest_MD5_50000_01_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = C8FB22BCB9F454DA44BA80C8 /* Validation_BloomFilterTest_MD5_50000_01_membership_test_result.json */; }; 7E82D412BB56728BEBB7EF46 /* bundle_serializer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5C2A94EE24E60543F62CC35 /* bundle_serializer_test.cc */; }; - 7E873E95A1C12646B7C22502 /* Pods_Firestore_Benchmarks_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29656CF5FBF6FA0230D7B6EA /* Pods_Firestore_Benchmarks_iOS.framework */; }; 7E97B0F04E25610FF37E9259 /* memory_target_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2286F308EFB0534B1BDE05B9 /* memory_target_cache_test.cc */; }; 7EAB3129A58368EE4BD449ED /* leveldb_migrations_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EF83ACD5E1E9F25845A9ACED /* leveldb_migrations_test.cc */; }; 7EF540911720DAAF516BEDF0 /* query_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B9C261C26C5D311E1E3C0CB9 /* query_test.cc */; }; @@ -1032,6 +1033,7 @@ 804B0C6CCE3933CF3948F249 /* grpc_streaming_reader_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D964922154AB8F00EB9CFB /* grpc_streaming_reader_test.cc */; }; 8077722A6BB175D3108CDC55 /* leveldb_remote_document_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0840319686A223CC4AD3FAB1 /* leveldb_remote_document_cache_test.cc */; }; 80AB93C807F35539EEC510B2 /* leveldb_lru_garbage_collector_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B629525F7A1AAC1AB765C74F /* leveldb_lru_garbage_collector_test.cc */; }; + 80C7B289B8FDF74171C8E8AE /* Pods_Firestore_Tests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C122EDA4E22AC055A2C20188 /* Pods_Firestore_Tests_iOS.framework */; }; 80D7FEBB1056E489F24C6C8F /* firebase_app_check_credentials_provider_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = F119BDDF2F06B3C0883B8297 /* firebase_app_check_credentials_provider_test.mm */; }; 80D8B7D6FFFEA12AF10E4E2B /* leveldb_overlay_migration_manager_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D8A6D52723B1BABE1B7B8D8F /* leveldb_overlay_migration_manager_test.cc */; }; 814724DE70EFC3DDF439CD78 /* executor_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6FB4688208F9B9100554BA2 /* executor_test.cc */; }; @@ -1118,6 +1120,7 @@ 8F3AE423677A4C50F7E0E5C0 /* database_info_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB38D92E20235D22000A432D /* database_info_test.cc */; }; 8F4F40E9BC7ED588F67734D5 /* app_testing.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5467FB07203E6A44009C9584 /* app_testing.mm */; }; 8F781F527ED72DC6C123689E /* autoid_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54740A521FC913E500713A1A /* autoid_test.cc */; }; + 8FCF385D67253C420F20A988 /* Pods_Firestore_IntegrationTests_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 382B8804885800C1BF8F9F45 /* Pods_Firestore_IntegrationTests_macOS.framework */; }; 9009C285F418EA80C46CF06B /* fake_target_metadata_provider.cc in Sources */ = {isa = PBXBuildFile; fileRef = 71140E5D09C6E76F7C71B2FC /* fake_target_metadata_provider.cc */; }; 900D0E9F18CE3DB954DD0D1E /* async_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6FB467B208E9A8200554BA2 /* async_queue_test.cc */; }; 90101123ABFB4DC13EC3EB0F /* mirroring_semantics_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F3704E3BF509EE783D0B0F08 /* mirroring_semantics_test.cc */; }; @@ -1150,7 +1153,6 @@ 94854FAEAEA75A1AC77A0515 /* memory_bundle_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB4AB1388538CD3CB19EB028 /* memory_bundle_cache_test.cc */; }; 94BBB23B93E449D03FA34F87 /* mutation_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3068AA9DFBBA86C1FE2A946E /* mutation_queue_test.cc */; }; 94C86F03FF86690307F28182 /* Validation_BloomFilterTest_MD5_5000_0001_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = C8582DFD74E8060C7072104B /* Validation_BloomFilterTest_MD5_5000_0001_membership_test_result.json */; }; - 94EC0C2B013259594DA44983 /* Pods_Firestore_Example_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 56DFA1A5F0D4F7CE4F014158 /* Pods_Firestore_Example_tvOS.framework */; }; 95490163C98C4F8AFD019730 /* comparison_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 87DD1A65EBA9FFC1FFAAE657 /* comparison_test.cc */; }; 95C0F55813DA51E6B8C439E1 /* status_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5493A423225F9990006DE7BA /* status_apple_test.mm */; }; 95CE3F5265B9BB7297EE5A6B /* lru_garbage_collector_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 277EAACC4DD7C21332E8496A /* lru_garbage_collector_test.cc */; }; @@ -1174,7 +1176,6 @@ 98FE82875A899A40A98AAC22 /* leveldb_opener_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 75860CD13AF47EB1EA39EC2F /* leveldb_opener_test.cc */; }; 990EC10E92DADB7D86A4BEE3 /* string_format_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54131E9620ADE678001DF3FF /* string_format_test.cc */; }; 992DD6779C7A166D3A22E749 /* firebase_app_check_credentials_provider_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = F119BDDF2F06B3C0883B8297 /* firebase_app_check_credentials_provider_test.mm */; }; - 9948EC749F74B2FA50E96845 /* Pods_Firestore_Tests_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2696F7160BC0525999F33F85 /* Pods_Firestore_Tests_macOS.framework */; }; 9966167103B9714723A88669 /* Validation_BloomFilterTest_MD5_50000_1_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 3841925AA60E13A027F565E6 /* Validation_BloomFilterTest_MD5_50000_1_membership_test_result.json */; }; 99F97B28DA546D42AB14214B /* comparison_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 87DD1A65EBA9FFC1FFAAE657 /* comparison_test.cc */; }; 9A29D572C64CA1FA62F591D4 /* FIRQueryTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E069202154D500B64F25 /* FIRQueryTests.mm */; }; @@ -1343,7 +1344,6 @@ B40EDE2B1B228ED59CF62788 /* byte_stream_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7628664347B9C96462D4BF17 /* byte_stream_apple_test.mm */; }; B41B17163DD9A421F35DE1A9 /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 57F8EE51B5EFC9FAB185B66C /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json */; }; B43014A0517F31246419E08A /* resume_token_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA12A41F315EE100DD57A1 /* resume_token_spec_test.json */; }; - B4321FCCCFBC787BF1109FC5 /* Pods_Firestore_Tests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8B9310A8C2FA2201E1261B4 /* Pods_Firestore_Tests_tvOS.framework */; }; B46E778F9E40864B5D2B2F1C /* leveldb_transaction_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 88CF09277CFA45EE1273E3BA /* leveldb_transaction_test.cc */; }; B491EF0E70DC0542644F623E /* Validation_BloomFilterTest_MD5_500_1_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 8AB49283E544497A9C5A0E59 /* Validation_BloomFilterTest_MD5_500_1_membership_test_result.json */; }; B4C675BE9030D5C7D19C4D19 /* ordered_code_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB380D03201BC6E400D97691 /* ordered_code_test.cc */; }; @@ -1439,7 +1439,6 @@ BFBE4732E93E38317B110778 /* index_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 8C7278B604B8799F074F4E8C /* index_spec_test.json */; }; BFCDC78CD851F109EB7A1422 /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 57F8EE51B5EFC9FAB185B66C /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json */; }; BFEAC4151D3AA8CE1F92CC2D /* FSTSpecTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E03020213FFC00B64F25 /* FSTSpecTests.mm */; }; - BFFF80B66D9D8BDB91844575 /* Pods_Firestore_IntegrationTests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E99993350B9F360190C6A886 /* Pods_Firestore_IntegrationTests_tvOS.framework */; }; C02A969BF4BB63ABCB531B4B /* create_noop_connectivity_monitor.cc in Sources */ = {isa = PBXBuildFile; fileRef = CF39535F2C41AB0006FA6C0E /* create_noop_connectivity_monitor.cc */; }; C06E54352661FCFB91968640 /* mutation_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3068AA9DFBBA86C1FE2A946E /* mutation_queue_test.cc */; }; C099AEC05D44976755BA32A2 /* thread_safe_memoizer_testing_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EA10515F99A42D71DA2D2841 /* thread_safe_memoizer_testing_test.cc */; }; @@ -1659,6 +1658,7 @@ E2AE851F9DC4C037CCD05E36 /* remote_document_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7EB299CF85034F09CFD6F3FD /* remote_document_cache_test.cc */; }; E2B15548A3B6796CE5A01975 /* FIRListenerRegistrationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E06B202154D500B64F25 /* FIRListenerRegistrationTests.mm */; }; E2B7AEDCAAC5AD74C12E85C1 /* datastore_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3167BD972EFF8EC636530E59 /* datastore_test.cc */; }; + E2D072512B6DB1835DEE55F1 /* Pods_Firestore_Example_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7722654712A76635B9F95AA /* Pods_Firestore_Example_tvOS.framework */; }; E30BF9E316316446371C956C /* persistence_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9113B6F513D0473AEABBAF1F /* persistence_testing.cc */; }; E3319DC1804B69F0ED1FFE02 /* memory_mutation_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 74FBEFA4FE4B12C435011763 /* memory_mutation_queue_test.cc */; }; E375FBA0632EFB4D14C4E5A9 /* FSTGoogleTestTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */; }; @@ -1907,8 +1907,9 @@ 0458BABD8F8738AD16F4A2FE /* array_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = array_test.cc; path = expressions/array_test.cc; sourceTree = ""; }; 045D39C4A7D52AF58264240F /* remote_document_cache_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = remote_document_cache_test.h; sourceTree = ""; }; 0473AFFF5567E667A125347B /* ordered_code_benchmark.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = ordered_code_benchmark.cc; sourceTree = ""; }; - 04F95FB0B1123006B5DA8153 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Benchmarks_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS.release.xcconfig"; sourceTree = ""; }; 062072B62773A055001655D7 /* AsyncAwaitIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncAwaitIntegrationTests.swift; sourceTree = ""; }; + 06362D2AFB59B3AB4DAE38CF /* Pods_Firestore_Benchmarks_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Benchmarks_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 06D1849DBC8EB170168B7FBA /* Pods-Firestore_Example_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS.debug.xcconfig"; sourceTree = ""; }; 0840319686A223CC4AD3FAB1 /* leveldb_remote_document_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_remote_document_cache_test.cc; sourceTree = ""; }; 09885253E010E281EC2773C4 /* where_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = where_test.cc; path = pipeline/where_test.cc; sourceTree = ""; }; 09C56D14F17CA02A07C60847 /* unicode_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = unicode_test.cc; path = pipeline/unicode_test.cc; sourceTree = ""; }; @@ -1934,18 +1935,18 @@ 1C3F7302BF4AE6CBC00ECDD0 /* resource.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = resource.pb.cc; sourceTree = ""; }; 1CA9800A53669EFBFFB824E3 /* memory_remote_document_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_remote_document_cache_test.cc; sourceTree = ""; }; 1E0C7C0DCD2790019E66D8CC /* bloom_filter.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = bloom_filter.pb.cc; sourceTree = ""; }; + 1EA35EF4A5508688A82334C9 /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig"; sourceTree = ""; }; 1F50E872B3F117A674DA8E94 /* index_backfiller_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = index_backfiller_test.cc; sourceTree = ""; }; 1F78CD3208A1D5885B4C134E /* field_behavior.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = field_behavior.pb.cc; sourceTree = ""; }; - 20C55A10362C9BDE9FB8C5E1 /* Pods-Firestore_Example_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS.release.xcconfig"; sourceTree = ""; }; 214877F52A705012D6720CA0 /* object_value_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = object_value_test.cc; sourceTree = ""; }; + 2231749BC05407EADF72CB29 /* Pods_Firestore_Tests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2286F308EFB0534B1BDE05B9 /* memory_target_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_target_cache_test.cc; sourceTree = ""; }; 24F0F49F016E65823E0075DB /* field_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = field_test.cc; path = expressions/field_test.cc; sourceTree = ""; }; - 2696F7160BC0525999F33F85 /* Pods_Firestore_Tests_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2565B04EF9072C15071E0FB3 /* Pods-Firestore_Example_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS.release.xcconfig"; sourceTree = ""; }; 26DDBA115DEB88631B93F203 /* thread_safe_memoizer_testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = thread_safe_memoizer_testing.h; sourceTree = ""; }; 277EAACC4DD7C21332E8496A /* lru_garbage_collector_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = lru_garbage_collector_test.cc; sourceTree = ""; }; 28034BA61A7395543F1508B3 /* maybe_document.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = maybe_document.pb.cc; sourceTree = ""; }; 28B45B2104E2DAFBBF86DBB7 /* logic_utils_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = logic_utils_test.cc; sourceTree = ""; }; - 29656CF5FBF6FA0230D7B6EA /* Pods_Firestore_Benchmarks_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Benchmarks_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2996F8E339AD187C2C5068DE /* utils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = utils.h; path = pipeline/utils.h; sourceTree = ""; }; 29D9C76922DAC6F710BC1EF4 /* memory_document_overlay_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_document_overlay_cache_test.cc; sourceTree = ""; }; 2A0CF41BA5AED6049B0BEB2C /* objc_type_traits_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = objc_type_traits_apple_test.mm; sourceTree = ""; }; @@ -1958,13 +1959,16 @@ 3081975D68903993303FA256 /* collection_group_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = collection_group_test.cc; path = pipeline/collection_group_test.cc; sourceTree = ""; }; 312E4667E3D994592C77B63C /* byte_stream_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = byte_stream_test.h; sourceTree = ""; }; 3167BD972EFF8EC636530E59 /* datastore_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = datastore_test.cc; sourceTree = ""; }; - 319C19479B01F7DEEAD9774A /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS.release.xcconfig"; sourceTree = ""; }; + 324ACEF203B31D0C0C727635 /* Pods-Firestore_Example_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS.release.xcconfig"; sourceTree = ""; }; 32C7CB095CD53D07E98D74B8 /* bundle.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = bundle.pb.h; sourceTree = ""; }; 332485C4DCC6BA0DBB5E31B7 /* leveldb_util_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_util_test.cc; sourceTree = ""; }; 3355BE9391CC4857AF0BDAE3 /* DatabaseTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DatabaseTests.swift; sourceTree = ""; }; 33607A3AE91548BD219EC9C6 /* transform_operation_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = transform_operation_test.cc; sourceTree = ""; }; 3369AC938F82A70685C5ED58 /* Validation_BloomFilterTest_MD5_1_1_membership_test_result.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_1_1_membership_test_result.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_1_1_membership_test_result.json; sourceTree = ""; }; 358C3B5FE573B1D60A4F7592 /* strerror_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = strerror_test.cc; sourceTree = ""; }; + 36121362F78AB49532007335 /* Pods-Firestore_Example_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS.debug.xcconfig"; sourceTree = ""; }; + 3764417D8A7C5DC5F07D4FAC /* Pods-Firestore_Tests_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS.debug.xcconfig"; sourceTree = ""; }; + 382B8804885800C1BF8F9F45 /* Pods_Firestore_IntegrationTests_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3841925AA60E13A027F565E6 /* Validation_BloomFilterTest_MD5_50000_1_membership_test_result.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_50000_1_membership_test_result.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_50000_1_membership_test_result.json; sourceTree = ""; }; 395E8B07639E69290A929695 /* index.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = index.pb.cc; path = admin/index.pb.cc; sourceTree = ""; }; 3B843E4A1F3930A400548890 /* remote_store_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = remote_store_spec_test.json; sourceTree = ""; }; @@ -1981,19 +1985,16 @@ 4375BDCDBCA9938C7F086730 /* Validation_BloomFilterTest_MD5_5000_1_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_5000_1_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_5000_1_bloom_filter_proto.json; sourceTree = ""; }; 444B7AB3F5A2929070CB1363 /* hard_assert_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = hard_assert_test.cc; sourceTree = ""; }; 4564AD9C55EC39C080EB9476 /* globals_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = globals_cache_test.cc; sourceTree = ""; }; - 459864A45E38975067B09B19 /* Pods-Firestore_Example_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS.release.xcconfig"; sourceTree = ""; }; 478DC75A0DCA6249A616DD30 /* Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json; sourceTree = ""; }; 48D0915834C3D234E5A875A9 /* grpc_stream_tester.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = grpc_stream_tester.h; sourceTree = ""; }; 4B0A3187AAD8B02135E80C2E /* collection_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = collection_test.cc; path = pipeline/collection_test.cc; sourceTree = ""; }; 4B3E4A77493524333133C5DC /* Validation_BloomFilterTest_MD5_50000_1_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_50000_1_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_50000_1_bloom_filter_proto.json; sourceTree = ""; }; 4B59C0A7B2A4548496ED4E7D /* Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json; sourceTree = ""; }; - 4BB169579995C73A8BF4D981 /* Pods-Firestore_Tests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS.debug.xcconfig"; sourceTree = ""; }; 4BD051DBE754950FEAC7A446 /* Validation_BloomFilterTest_MD5_500_01_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_500_01_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_500_01_bloom_filter_proto.json; sourceTree = ""; }; 4C73C0CC6F62A90D8573F383 /* string_apple_benchmark.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = string_apple_benchmark.mm; sourceTree = ""; }; + 4D1A32406F36DE4ACF604E93 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Benchmarks_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS.release.xcconfig"; sourceTree = ""; }; 4D65F6E69993611D47DC8E7C /* SnapshotListenerSourceTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SnapshotListenerSourceTests.swift; sourceTree = ""; }; 4D9E51DA7A275D8B1CAEAEB2 /* listen_source_spec_test.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; path = listen_source_spec_test.json; sourceTree = ""; }; - 4DD0B43814F694A7004F307F /* Pods_Firestore_IntegrationTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4EAA1E2AC6B9AD4D3876C451 /* Pods-Firestore_Tests_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS.debug.xcconfig"; sourceTree = ""; }; 4F5B96F3ABCD2CA901DB1CD4 /* bundle_builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = bundle_builder.cc; sourceTree = ""; }; 51004EAF5EE01ADCE8FE3788 /* canonify_eq_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = canonify_eq_test.cc; path = pipeline/canonify_eq_test.cc; sourceTree = ""; }; 526D755F65AC676234F57125 /* target_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = target_test.cc; sourceTree = ""; }; @@ -2098,8 +2099,8 @@ 54E9281E1F33950B00C1953E /* FSTIntegrationTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSTIntegrationTestCase.h; sourceTree = ""; }; 54E9282A1F339CAD00C1953E /* XCTestCase+Await.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCTestCase+Await.h"; sourceTree = ""; }; 54EB764C202277B30088B8F3 /* array_sorted_map_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = array_sorted_map_test.cc; sourceTree = ""; }; - 56DFA1A5F0D4F7CE4F014158 /* Pods_Firestore_Example_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 57F8EE51B5EFC9FAB185B66C /* Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_5000_01_bloom_filter_proto.json; sourceTree = ""; }; + 581E1E6A034002250995098C /* Pods-Firestore_Tests_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS.release.xcconfig"; sourceTree = ""; }; 584AE2C37A55B408541A6FF3 /* remote_event_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = remote_event_test.cc; sourceTree = ""; }; 59BF06E5A4988F9F949DD871 /* PipelineApiTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PipelineApiTests.swift; sourceTree = ""; }; 5B5414D28802BC76FDADABD6 /* stream_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = stream_test.cc; sourceTree = ""; }; @@ -2109,7 +2110,6 @@ 5C7942B6244F4C416B11B86C /* leveldb_mutation_queue_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_mutation_queue_test.cc; sourceTree = ""; }; 5CAE131920FFFED600BE9A4A /* Firestore_Benchmarks_iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Firestore_Benchmarks_iOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5CAE131D20FFFED600BE9A4A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 5DC11E3981B81DDFF8A4453B /* Pods-Firestore_Tests_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS.release.xcconfig"; sourceTree = ""; }; 5E19B9B2105BA618DA9EE99C /* query_engine_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = query_engine_test.h; sourceTree = ""; }; 5FF903AEFA7A3284660FA4C5 /* leveldb_local_store_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_local_store_test.cc; sourceTree = ""; }; 6003F58A195388D20070C39A /* Firestore_Example_iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Firestore_Example_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2148,15 +2148,16 @@ 620C1427763BA5D3CCFB5A1F /* BridgingHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = BridgingHeader.h; sourceTree = ""; }; 621D620928F9CE7400D2FA26 /* QueryIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryIntegrationTests.swift; sourceTree = ""; }; 6271643B2ED4D5EE00D2CD1D /* RealtimePipelineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimePipelineTests.swift; sourceTree = ""; }; + 627AF76D2EDF45F300D23311 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 62E54B832A9E910A003347C8 /* IndexingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndexingTests.swift; sourceTree = ""; }; 63136A2371C0C013EC7A540C /* target_index_matcher_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = target_index_matcher_test.cc; sourceTree = ""; }; 64AA92CFA356A2360F3C5646 /* filesystem_testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = filesystem_testing.h; sourceTree = ""; }; 6534F87DEF534CEEF672ADC5 /* number_semantics_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = number_semantics_test.cc; path = pipeline/number_semantics_test.cc; sourceTree = ""; }; 65AF0AB593C3AD81A1F1A57E /* FIRCompositeIndexQueryTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRCompositeIndexQueryTests.mm; sourceTree = ""; }; + 66A73B45396313D614B1FC96 /* Pods_Firestore_IntegrationTests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 67786C62C76A740AEDBD8CD3 /* FSTTestingHooks.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FSTTestingHooks.h; sourceTree = ""; }; 6A7A30A2DB3367E08939E789 /* bloom_filter.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = bloom_filter.pb.h; sourceTree = ""; }; - 6ABFEF8FB2361EEE737CB120 /* Pods-Firestore_Example_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS.debug.xcconfig"; sourceTree = ""; }; - 6CA462CE027855D254A69006 /* Pods-Firestore_Example_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS.release.xcconfig"; sourceTree = ""; }; + 6AC7F3A6784E9FAE5E15D082 /* Pods-Firestore_Example_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS.debug.xcconfig"; sourceTree = ""; }; 6E42FA109D363EA7F3387AAE /* thread_safe_memoizer_testing.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = thread_safe_memoizer_testing.cc; sourceTree = ""; }; 6E8302DE210222ED003E1EA3 /* FSTFuzzTestFieldPath.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSTFuzzTestFieldPath.h; sourceTree = ""; }; 6E8302DF21022309003E1EA3 /* FSTFuzzTestFieldPath.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTFuzzTestFieldPath.mm; sourceTree = ""; }; @@ -2169,6 +2170,7 @@ 6EDD3B5E20BF24D000C33877 /* FSTFuzzTestsPrincipal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTFuzzTestsPrincipal.mm; sourceTree = ""; }; 6F57521E161450FAF89075ED /* event_manager_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = event_manager_test.cc; sourceTree = ""; }; 6F5B6C1399F92FD60F2C582B /* nanopb_util_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = nanopb_util_test.cc; path = nanopb/nanopb_util_test.cc; sourceTree = ""; }; + 7054E3FD979D9C8E870DB6BB /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS.debug.xcconfig"; sourceTree = ""; }; 71140E5D09C6E76F7C71B2FC /* fake_target_metadata_provider.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = fake_target_metadata_provider.cc; sourceTree = ""; }; 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 728F617782600536F2561463 /* Validation_BloomFilterTest_MD5_5000_0001_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_5000_0001_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_5000_0001_bloom_filter_proto.json; sourceTree = ""; }; @@ -2180,9 +2182,9 @@ 75860CD13AF47EB1EA39EC2F /* leveldb_opener_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_opener_test.cc; sourceTree = ""; }; 75E24C5CD7BC423D48713100 /* counting_query_engine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = counting_query_engine.h; sourceTree = ""; }; 7628664347B9C96462D4BF17 /* byte_stream_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = byte_stream_apple_test.mm; sourceTree = ""; }; - 765CEDF282B8255A337CEF80 /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig"; sourceTree = ""; }; 76EED4ED84056B623D92FE20 /* arithmetic_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = arithmetic_test.cc; path = expressions/arithmetic_test.cc; sourceTree = ""; }; 776530F066E788C355B78457 /* FIRBundlesTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRBundlesTests.mm; sourceTree = ""; }; + 788BBE9FBC7D1148D4BD6FC2 /* Pods_Firestore_Example_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 78EE0BFC7E60C4929458A0EA /* resource.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = resource.pb.h; sourceTree = ""; }; 79507DF8378D3C42F5B36268 /* string_win_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = string_win_test.cc; sourceTree = ""; }; 795AA8FC31D2AF6864B07D39 /* FIRIndexingTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRIndexingTests.mm; sourceTree = ""; }; @@ -2194,10 +2196,9 @@ 7C5C40C7BFBB86032F1DC632 /* FSTExceptionCatcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FSTExceptionCatcher.h; sourceTree = ""; }; 7EB299CF85034F09CFD6F3FD /* remote_document_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = remote_document_cache_test.cc; sourceTree = ""; }; 82DF854A7238D538FA53C908 /* timestamp_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = timestamp_test.cc; path = expressions/timestamp_test.cc; sourceTree = ""; }; - 82FFAF9DBBA0F7ABD2A0AEAD /* Pods_Firestore_Example_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 831CE94805EAC3F88B9019DA /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS.debug.xcconfig"; sourceTree = ""; }; 84076EADF6872C78CDAC7291 /* bundle_builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = bundle_builder.h; sourceTree = ""; }; 861684E49DAC993D153E60D0 /* PipelineTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PipelineTests.swift; sourceTree = ""; }; + 8696B66E66E4C8B036459A5E /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS.debug.xcconfig"; sourceTree = ""; }; 86C7F725E6E1DA312807D8D3 /* explain_stats.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = explain_stats.pb.h; sourceTree = ""; }; 872C92ABD71B12784A1C5520 /* async_testing.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = async_testing.cc; sourceTree = ""; }; 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -2212,26 +2213,27 @@ 8C058C8BE2723D9A53CCD64B /* persistence_testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = persistence_testing.h; sourceTree = ""; }; 8C7278B604B8799F074F4E8C /* index_spec_test.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; path = index_spec_test.json; sourceTree = ""; }; 8D9892F204959C50613F16C8 /* FSTUserDataReaderTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTUserDataReaderTests.mm; sourceTree = ""; }; - 8DB38D2B14D3955ACA3F3952 /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS.release.xcconfig"; sourceTree = ""; }; 8E002F4AD5D9B6197C940847 /* Firestore.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Firestore.podspec; path = ../Firestore.podspec; sourceTree = ""; }; - 8E41D518EC9B6079252C063D /* Pods_Firestore_Example_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8E9CD82E60893DDD7757B798 /* leveldb_bundle_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_bundle_cache_test.cc; sourceTree = ""; }; 8EF6A33BC2D84233C355F1D0 /* memory_query_engine_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_query_engine_test.cc; sourceTree = ""; }; 8F1A7B4158D9DD76EE4836BF /* load_bundle_task_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = load_bundle_task_test.cc; path = api/load_bundle_task_test.cc; sourceTree = ""; }; 8FA60B08D59FEA0D6751E87F /* empty_credentials_provider_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = empty_credentials_provider_test.cc; path = credentials/empty_credentials_provider_test.cc; sourceTree = ""; }; 9098A0C535096F2EE9C35DE0 /* create_noop_connectivity_monitor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = create_noop_connectivity_monitor.h; sourceTree = ""; }; + 90D3C05AE151D47E2CAF3758 /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Benchmarks_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS.debug.xcconfig"; sourceTree = ""; }; 9113B6F513D0473AEABBAF1F /* persistence_testing.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = persistence_testing.cc; sourceTree = ""; }; - 949E444D7EAA5BE81BBE5E5E /* Pods_Firestore_IntegrationTests_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 920E8C520B88EA78346BB86D /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS.release.xcconfig"; sourceTree = ""; }; + 921DD3C8DFD768101F11AE9E /* Pods-Firestore_Tests_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS.debug.xcconfig"; sourceTree = ""; }; 9765D47FA12FA283F4EFAD02 /* memory_lru_garbage_collector_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_lru_garbage_collector_test.cc; sourceTree = ""; }; 99434327614FEFF7F7DC88EC /* counting_query_engine.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = counting_query_engine.cc; sourceTree = ""; }; 9B0B005A79E765AF02793DCE /* schedule_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = schedule_test.cc; sourceTree = ""; }; 9C1AFCC9E616EC33D6E169CF /* recovery_spec_test.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; path = recovery_spec_test.json; sourceTree = ""; }; 9CFD366B783AE27B9E79EE7A /* string_format_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = string_format_apple_test.mm; sourceTree = ""; }; - 9DE6467395E0973563A0BF9D /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_macOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS.debug.xcconfig"; sourceTree = ""; }; + 9D9E3DFC76D84FC2554F47B3 /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS.release.xcconfig"; sourceTree = ""; }; 9E60C06991E3D28A0F70DD8D /* globals_cache_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = globals_cache_test.h; sourceTree = ""; }; 9F12A488C443DBCCEC54DB61 /* pipeline_util_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = pipeline_util_test.cc; sourceTree = ""; }; A002425BC4FC4E805F4175B6 /* testing_hooks_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = testing_hooks_test.cc; sourceTree = ""; }; A082AFDD981B07B5AD78FDE8 /* token_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = token_test.cc; path = credentials/token_test.cc; sourceTree = ""; }; + A1439162E5B5C2C81A2BCB02 /* Pods-Firestore_Example_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS.release.xcconfig"; sourceTree = ""; }; A20BAA3D2F994384279727EC /* md5_testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = md5_testing.h; sourceTree = ""; }; A2E6F09AD1EE0A6A452E9A08 /* bloom_filter_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = bloom_filter_test.cc; sourceTree = ""; }; A366F6AE1A5A77548485C091 /* bundle.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = bundle.pb.cc; sourceTree = ""; }; @@ -2286,13 +2288,14 @@ B8A853940305237AFDA8050B /* query_engine_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = query_engine_test.cc; sourceTree = ""; }; B8BFD9B37D1029D238BDD71E /* FSTExceptionCatcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FSTExceptionCatcher.m; sourceTree = ""; }; B9C261C26C5D311E1E3C0CB9 /* query_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = query_test.cc; sourceTree = ""; }; + B9E41EFAB22DF1E7B475AE96 /* Pods-Firestore_Tests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS.debug.xcconfig"; sourceTree = ""; }; B9ED38DA914BDCD2E3A0714D /* aggregation_result.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = aggregation_result.pb.h; sourceTree = ""; }; BA02DA2FCD0001CFC6EB08DA /* filesystem_testing.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = filesystem_testing.cc; sourceTree = ""; }; BA4CBA48204C9E25B56993BC /* fields_array_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = fields_array_test.cc; path = nanopb/fields_array_test.cc; sourceTree = ""; }; BC3C788D290A935C353CEAA1 /* writer_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = writer_test.cc; path = nanopb/writer_test.cc; sourceTree = ""; }; - BD030C308116480114144B89 /* Pods-Firestore_Example_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS.debug.xcconfig"; sourceTree = ""; }; BF76A8DA34B5B67B4DD74666 /* field_index_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = field_index_test.cc; sourceTree = ""; }; C0C7C8977C94F9F9AFA4DB00 /* local_store_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = local_store_test.h; sourceTree = ""; }; + C122EDA4E22AC055A2C20188 /* Pods_Firestore_Tests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C7429071B33BDF80A7FA2F8A /* view_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = view_test.cc; sourceTree = ""; }; C8522DE226C467C54E6788D8 /* mutation_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = mutation_test.cc; sourceTree = ""; }; C8582DFD74E8060C7072104B /* Validation_BloomFilterTest_MD5_5000_0001_membership_test_result.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_5000_0001_membership_test_result.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_5000_0001_membership_test_result.json; sourceTree = ""; }; @@ -2301,15 +2304,17 @@ CB7B2D4691C380DE3EB59038 /* lru_garbage_collector_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = lru_garbage_collector_test.h; sourceTree = ""; }; CB852EE6E7D301545700BFD8 /* map_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = map_test.cc; path = expressions/map_test.cc; sourceTree = ""; }; CC572A9168BBEF7B83E4BBC5 /* view_snapshot_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = view_snapshot_test.cc; sourceTree = ""; }; - CC85FC848368E88FA264A1BE /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS.release.xcconfig"; sourceTree = ""; }; CCC9BD953F121B9E29F9AA42 /* user_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = user_test.cc; path = credentials/user_test.cc; sourceTree = ""; }; CD422AF3E4515FB8E9BE67A0 /* equals_tester.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = equals_tester.h; sourceTree = ""; }; CDC018C1D4CEC9B131449F98 /* expression_test_util.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = expression_test_util.h; sourceTree = ""; }; CE37875365497FFA8687B745 /* message_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = message_test.cc; path = nanopb/message_test.cc; sourceTree = ""; }; + CEF63D0E366F0D07AFC234EC /* Pods_Firestore_Tests_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CF39535F2C41AB0006FA6C0E /* create_noop_connectivity_monitor.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = create_noop_connectivity_monitor.cc; sourceTree = ""; }; CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRTransactionOptionsTests.mm; sourceTree = ""; }; + CFD0175464350438D3A4F756 /* Pods_Firestore_Example_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D0A6E9136804A41CEC9D55D4 /* delayed_constructor_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = delayed_constructor_test.cc; sourceTree = ""; }; D22D4C211AC32E4F8B4883DA /* Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json; sourceTree = ""; }; + D2FE5F3EBFEC54350FFB9DDF /* Pods_Firestore_IntegrationTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D3CC3DC5338DCAF43A211155 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; D49E7AEE500651D25C5360C3 /* pipeline.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = pipeline.pb.cc; sourceTree = ""; }; D5B2593BCB52957D62F1C9D3 /* perf_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = perf_spec_test.json; sourceTree = ""; }; @@ -2317,7 +2322,6 @@ D85AC18C55650ED230A71B82 /* FSTTestingHooks.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTTestingHooks.mm; sourceTree = ""; }; D872D754B8AD88E28AF28B28 /* aggregation_result.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = aggregation_result.pb.cc; sourceTree = ""; }; D8A6D52723B1BABE1B7B8D8F /* leveldb_overlay_migration_manager_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_overlay_migration_manager_test.cc; sourceTree = ""; }; - D8B9310A8C2FA2201E1261B4 /* Pods_Firestore_Tests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D8E530B27D5641B9C26A452C /* Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json; sourceTree = ""; }; D9D94300B9C02F7069523C00 /* leveldb_snappy_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_snappy_test.cc; sourceTree = ""; }; DAFF0CF521E64AC30062958F /* Firestore_Example_macOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Firestore_Example_macOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2328,6 +2332,7 @@ DAFF0CFF21E64AC40062958F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DAFF0D0021E64AC40062958F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; DAFF0D0221E64AC40062958F /* macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = ""; }; + DB19B825EC1F2680D3D5F040 /* Pods-Firestore_Tests_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS.release.xcconfig"; sourceTree = ""; }; DB1F1E1B1ED15E8D042144B1 /* leveldb_query_engine_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_query_engine_test.cc; sourceTree = ""; }; DB5A1E760451189DA36028B3 /* memory_index_manager_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_index_manager_test.cc; sourceTree = ""; }; DD12BC1DB2480886D2FB0005 /* settings_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = settings_test.cc; path = api/settings_test.cc; sourceTree = ""; }; @@ -2340,16 +2345,14 @@ DE51B1981F0D48AC0013853F /* FSTSpecTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSTSpecTests.h; sourceTree = ""; }; DE51B19A1F0D48AC0013853F /* FSTSyncEngineTestDriver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSTSyncEngineTestDriver.h; sourceTree = ""; }; DE51B1A71F0D48AC0013853F /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - DE9C9075C63C66F01961750F /* Pods-Firestore_Tests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS.release.xcconfig"; sourceTree = ""; }; DF445D5201750281F1817387 /* document_overlay_cache_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = document_overlay_cache_test.h; sourceTree = ""; }; - DFB2CD94DF4A37DCC987E3CC /* Pods-Firestore_Example_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS.debug.xcconfig"; sourceTree = ""; }; E1459FA70B8FC18DE4B80D0D /* overlay_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = overlay_test.cc; sourceTree = ""; }; E2E39422953DE1D3C7B97E77 /* md5_testing.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = md5_testing.cc; sourceTree = ""; }; E3228F51DCDC2E90D5C58F97 /* ConditionalConformanceTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConditionalConformanceTests.swift; sourceTree = ""; }; + E6F6E872A9615A88736EACB7 /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_macOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS.release.xcconfig"; sourceTree = ""; }; E76F0CDF28E5FA62D21DE648 /* leveldb_target_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_target_cache_test.cc; sourceTree = ""; }; - E99993350B9F360190C6A886 /* Pods_Firestore_IntegrationTests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E7722654712A76635B9F95AA /* Pods_Firestore_Example_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; EA10515F99A42D71DA2D2841 /* thread_safe_memoizer_testing_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = thread_safe_memoizer_testing_test.cc; sourceTree = ""; }; - EC00431536EFDDE0256357E2 /* Pods-Firestore_Tests_tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS.debug.xcconfig"; sourceTree = ""; }; EEF23C7104A4D040C3A8CF9B /* string_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = string_test.cc; path = expressions/string_test.cc; sourceTree = ""; }; EF3A65472C66B9560041EE69 /* FIRVectorValueTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRVectorValueTests.mm; sourceTree = ""; }; EF6C285029E462A200A7D4F1 /* FIRAggregateTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRAggregateTests.mm; sourceTree = ""; }; @@ -2358,7 +2361,6 @@ EFF22EA92C5060A4009A369B /* VectorIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VectorIntegrationTests.swift; sourceTree = ""; }; F02F734F272C3C70D1307076 /* filter_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = filter_test.cc; sourceTree = ""; }; F119BDDF2F06B3C0883B8297 /* firebase_app_check_credentials_provider_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = firebase_app_check_credentials_provider_test.mm; path = credentials/firebase_app_check_credentials_provider_test.mm; sourceTree = ""; }; - F1F1CCCF68677C413FEFB2BC /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Benchmarks_iOS.debug.xcconfig"; path = "Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS.debug.xcconfig"; sourceTree = ""; }; F3704E3BF509EE783D0B0F08 /* mirroring_semantics_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = mirroring_semantics_test.cc; path = expressions/mirroring_semantics_test.cc; sourceTree = ""; }; F51619F8CFF13B0CDD13EDC3 /* logical_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = logical_test.cc; path = expressions/logical_test.cc; sourceTree = ""; }; F51859B394D01C0C507282F1 /* filesystem_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = filesystem_test.cc; sourceTree = ""; }; @@ -2366,10 +2368,9 @@ F6DBD8EDF0074DD0079ECCE6 /* debug_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = debug_test.cc; path = expressions/debug_test.cc; sourceTree = ""; }; F7FC06E0A47D393DE1759AE1 /* bundle_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = bundle_cache_test.cc; sourceTree = ""; }; F8043813A5D16963EC02B182 /* local_serializer_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = local_serializer_test.cc; sourceTree = ""; }; - F8222AA70B3B1CAA6CF73DE0 /* Pods-Firestore_Tests_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_tvOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS.release.xcconfig"; sourceTree = ""; }; F848C41C03A25C42AD5A4BC2 /* target_cache_test.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = target_cache_test.h; sourceTree = ""; }; + F8667425B6A18A7C98124FEF /* Pods-Firestore_Tests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_iOS.release.xcconfig"; path = "Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS.release.xcconfig"; sourceTree = ""; }; F869D85E900E5AF6CD02E2FC /* firebase_auth_credentials_provider_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = firebase_auth_credentials_provider_test.mm; path = credentials/firebase_auth_credentials_provider_test.mm; sourceTree = ""; }; - F9C6CD63A780B7E8F1EBF761 /* Pods_Firestore_Tests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FC44D934D4A52C790659C8D6 /* leveldb_globals_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_globals_cache_test.cc; sourceTree = ""; }; FF73B39D04D1760190E6B84A /* FIRQueryUnitTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRQueryUnitTests.mm; sourceTree = ""; }; FFCA39825D9678A03D1845D0 /* document_overlay_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = document_overlay_cache_test.cc; sourceTree = ""; }; @@ -2380,7 +2381,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9948EC749F74B2FA50E96845 /* Pods_Firestore_Tests_macOS.framework in Frameworks */, + 3C391CFCA34C3C982A2879E2 /* Pods_Firestore_Tests_macOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2388,7 +2389,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 94EC0C2B013259594DA44983 /* Pods_Firestore_Example_tvOS.framework in Frameworks */, + E2D072512B6DB1835DEE55F1 /* Pods_Firestore_Example_tvOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2396,7 +2397,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B4321FCCCFBC787BF1109FC5 /* Pods_Firestore_Tests_tvOS.framework in Frameworks */, + 360FE605D54DC67861B90C80 /* Pods_Firestore_Tests_tvOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2404,7 +2405,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - BFFF80B66D9D8BDB91844575 /* Pods_Firestore_IntegrationTests_tvOS.framework in Frameworks */, + 6613D37C71DD13DDEF7BCAD6 /* Pods_Firestore_IntegrationTests_tvOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2412,7 +2413,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 05A18C838432F611F21F1C53 /* Pods_Firestore_IntegrationTests_macOS.framework in Frameworks */, + 8FCF385D67253C420F20A988 /* Pods_Firestore_IntegrationTests_macOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2420,7 +2421,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 7E873E95A1C12646B7C22502 /* Pods_Firestore_Benchmarks_iOS.framework in Frameworks */, + 6E8432D9E9220A846C1FC4C4 /* Pods_Firestore_Benchmarks_iOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2430,8 +2431,8 @@ files = ( 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, + 3E4D0C53B43154D9FF0BC429 /* Pods_Firestore_Example_iOS.framework in Frameworks */, 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, - 3E81E93349135A3E814376F9 /* Pods_Firestore_Example_iOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2440,9 +2441,9 @@ buildActionMask = 2147483647; files = ( 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, + 80C7B289B8FDF74171C8E8AE /* Pods_Firestore_Tests_iOS.framework in Frameworks */, 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, - 352AA573D357554B9808D2CD /* Pods_Firestore_Tests_iOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2460,7 +2461,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 2951C96256ECD27C2165907A /* Pods_Firestore_Example_macOS.framework in Frameworks */, + 4A057F92BA79DAD4441B2380 /* Pods_Firestore_Example_macOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2469,9 +2470,9 @@ buildActionMask = 2147483647; files = ( DE03B2D61F2149D600A30B9C /* Foundation.framework in Frameworks */, + 6725C6773A3493E9221BEAC9 /* Pods_Firestore_IntegrationTests_iOS.framework in Frameworks */, DE03B2D51F2149D600A30B9C /* UIKit.framework in Frameworks */, DE03B2D41F2149D600A30B9C /* XCTest.framework in Frameworks */, - 175B5477F51147408A287F61 /* Pods_Firestore_IntegrationTests_iOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2856,6 +2857,7 @@ 6003F58C195388D20070C39A /* Frameworks */, 6003F58B195388D20070C39A /* Products */, 67DC68172636F7FE04B766D4 /* Pods */, + 627AF76D2EDF45F300D23311 /* GoogleService-Info.plist */, ); sourceTree = ""; }; @@ -2882,18 +2884,18 @@ children = ( 6003F58F195388D20070C39A /* CoreGraphics.framework */, 6003F58D195388D20070C39A /* Foundation.framework */, + 06362D2AFB59B3AB4DAE38CF /* Pods_Firestore_Benchmarks_iOS.framework */, + CFD0175464350438D3A4F756 /* Pods_Firestore_Example_iOS.framework */, + 788BBE9FBC7D1148D4BD6FC2 /* Pods_Firestore_Example_macOS.framework */, + E7722654712A76635B9F95AA /* Pods_Firestore_Example_tvOS.framework */, + D2FE5F3EBFEC54350FFB9DDF /* Pods_Firestore_IntegrationTests_iOS.framework */, + 382B8804885800C1BF8F9F45 /* Pods_Firestore_IntegrationTests_macOS.framework */, + 66A73B45396313D614B1FC96 /* Pods_Firestore_IntegrationTests_tvOS.framework */, + C122EDA4E22AC055A2C20188 /* Pods_Firestore_Tests_iOS.framework */, + CEF63D0E366F0D07AFC234EC /* Pods_Firestore_Tests_macOS.framework */, + 2231749BC05407EADF72CB29 /* Pods_Firestore_Tests_tvOS.framework */, 6003F591195388D20070C39A /* UIKit.framework */, 6003F5AF195388D20070C39A /* XCTest.framework */, - 29656CF5FBF6FA0230D7B6EA /* Pods_Firestore_Benchmarks_iOS.framework */, - 82FFAF9DBBA0F7ABD2A0AEAD /* Pods_Firestore_Example_iOS.framework */, - 8E41D518EC9B6079252C063D /* Pods_Firestore_Example_macOS.framework */, - 56DFA1A5F0D4F7CE4F014158 /* Pods_Firestore_Example_tvOS.framework */, - 4DD0B43814F694A7004F307F /* Pods_Firestore_IntegrationTests_iOS.framework */, - 949E444D7EAA5BE81BBE5E5E /* Pods_Firestore_IntegrationTests_macOS.framework */, - E99993350B9F360190C6A886 /* Pods_Firestore_IntegrationTests_tvOS.framework */, - F9C6CD63A780B7E8F1EBF761 /* Pods_Firestore_Tests_iOS.framework */, - 2696F7160BC0525999F33F85 /* Pods_Firestore_Tests_macOS.framework */, - D8B9310A8C2FA2201E1261B4 /* Pods_Firestore_Tests_tvOS.framework */, ); name = Frameworks; sourceTree = ""; @@ -3036,26 +3038,26 @@ 67DC68172636F7FE04B766D4 /* Pods */ = { isa = PBXGroup; children = ( - F1F1CCCF68677C413FEFB2BC /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */, - 04F95FB0B1123006B5DA8153 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */, - BD030C308116480114144B89 /* Pods-Firestore_Example_iOS.debug.xcconfig */, - 20C55A10362C9BDE9FB8C5E1 /* Pods-Firestore_Example_iOS.release.xcconfig */, - 6ABFEF8FB2361EEE737CB120 /* Pods-Firestore_Example_macOS.debug.xcconfig */, - 6CA462CE027855D254A69006 /* Pods-Firestore_Example_macOS.release.xcconfig */, - DFB2CD94DF4A37DCC987E3CC /* Pods-Firestore_Example_tvOS.debug.xcconfig */, - 459864A45E38975067B09B19 /* Pods-Firestore_Example_tvOS.release.xcconfig */, - 831CE94805EAC3F88B9019DA /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */, - 8DB38D2B14D3955ACA3F3952 /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */, - 9DE6467395E0973563A0BF9D /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */, - 319C19479B01F7DEEAD9774A /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */, - 765CEDF282B8255A337CEF80 /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */, - CC85FC848368E88FA264A1BE /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */, - 4BB169579995C73A8BF4D981 /* Pods-Firestore_Tests_iOS.debug.xcconfig */, - DE9C9075C63C66F01961750F /* Pods-Firestore_Tests_iOS.release.xcconfig */, - 4EAA1E2AC6B9AD4D3876C451 /* Pods-Firestore_Tests_macOS.debug.xcconfig */, - 5DC11E3981B81DDFF8A4453B /* Pods-Firestore_Tests_macOS.release.xcconfig */, - EC00431536EFDDE0256357E2 /* Pods-Firestore_Tests_tvOS.debug.xcconfig */, - F8222AA70B3B1CAA6CF73DE0 /* Pods-Firestore_Tests_tvOS.release.xcconfig */, + 90D3C05AE151D47E2CAF3758 /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */, + 4D1A32406F36DE4ACF604E93 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */, + 06D1849DBC8EB170168B7FBA /* Pods-Firestore_Example_iOS.debug.xcconfig */, + 2565B04EF9072C15071E0FB3 /* Pods-Firestore_Example_iOS.release.xcconfig */, + 6AC7F3A6784E9FAE5E15D082 /* Pods-Firestore_Example_macOS.debug.xcconfig */, + A1439162E5B5C2C81A2BCB02 /* Pods-Firestore_Example_macOS.release.xcconfig */, + 36121362F78AB49532007335 /* Pods-Firestore_Example_tvOS.debug.xcconfig */, + 324ACEF203B31D0C0C727635 /* Pods-Firestore_Example_tvOS.release.xcconfig */, + 7054E3FD979D9C8E870DB6BB /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */, + 920E8C520B88EA78346BB86D /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */, + 8696B66E66E4C8B036459A5E /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */, + E6F6E872A9615A88736EACB7 /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */, + 1EA35EF4A5508688A82334C9 /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */, + 9D9E3DFC76D84FC2554F47B3 /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */, + B9E41EFAB22DF1E7B475AE96 /* Pods-Firestore_Tests_iOS.debug.xcconfig */, + F8667425B6A18A7C98124FEF /* Pods-Firestore_Tests_iOS.release.xcconfig */, + 921DD3C8DFD768101F11AE9E /* Pods-Firestore_Tests_macOS.debug.xcconfig */, + 581E1E6A034002250995098C /* Pods-Firestore_Tests_macOS.release.xcconfig */, + 3764417D8A7C5DC5F07D4FAC /* Pods-Firestore_Tests_tvOS.debug.xcconfig */, + DB19B825EC1F2680D3D5F040 /* Pods-Firestore_Tests_tvOS.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -3381,11 +3383,11 @@ isa = PBXNativeTarget; buildConfigurationList = 544AB19B2248072200F851E6 /* Build configuration list for PBXNativeTarget "Firestore_Tests_macOS" */; buildPhases = ( - D0E2864849F7821EA1766350 /* [CP] Check Pods Manifest.lock */, + B63951B6F1AC344D56A285BB /* [CP] Check Pods Manifest.lock */, 544AB18E2248072200F851E6 /* Sources */, 544AB18F2248072200F851E6 /* Frameworks */, 544AB1902248072200F851E6 /* Resources */, - 470F142676C51630881DE722 /* [CP] Embed Pods Frameworks */, + 49223B384693551711FF9FBF /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3401,11 +3403,11 @@ isa = PBXNativeTarget; buildConfigurationList = 54AA33A1224BF936006CE580 /* Build configuration list for PBXNativeTarget "Firestore_Example_tvOS" */; buildPhases = ( - 9924014786EA7DE18926B94C /* [CP] Check Pods Manifest.lock */, + 5EB3B73D994059115EE9E133 /* [CP] Check Pods Manifest.lock */, 54AA338B224BF935006CE580 /* Sources */, 54AA338C224BF935006CE580 /* Frameworks */, 54AA338D224BF935006CE580 /* Resources */, - BFA27F7A0A2F3791CC6AD5F3 /* [CP] Embed Pods Frameworks */, + FCE4187347D5B0975354AC0D /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3420,11 +3422,11 @@ isa = PBXNativeTarget; buildConfigurationList = 54AA33AF224BFE0A006CE580 /* Build configuration list for PBXNativeTarget "Firestore_Tests_tvOS" */; buildPhases = ( - 4BFF87BC6397E978B275C6A8 /* [CP] Check Pods Manifest.lock */, + B97602CD18E190159B0EA450 /* [CP] Check Pods Manifest.lock */, 54AA33A2224BFE09006CE580 /* Sources */, 54AA33A3224BFE09006CE580 /* Frameworks */, 54AA33A4224BFE09006CE580 /* Resources */, - C28155D3E0ED2F6C48249B5F /* [CP] Embed Pods Frameworks */, + 8C54C9D79238315A22209F10 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3440,11 +3442,11 @@ isa = PBXNativeTarget; buildConfigurationList = 54AA33BB224C0035006CE580 /* Build configuration list for PBXNativeTarget "Firestore_IntegrationTests_tvOS" */; buildPhases = ( - C85CCD6E92EE34EA8E132CCC /* [CP] Check Pods Manifest.lock */, + 64F12822E1DB6C711C848A4C /* [CP] Check Pods Manifest.lock */, 54AA33B0224C0035006CE580 /* Sources */, 54AA33B1224C0035006CE580 /* Frameworks */, 54AA33B2224C0035006CE580 /* Resources */, - 4EFCC40FAD4523014466B872 /* [CP] Embed Pods Frameworks */, + C0DB68EB86D2339FF6498AD5 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3460,11 +3462,11 @@ isa = PBXNativeTarget; buildConfigurationList = 54B8E4B3224BDC4100930F18 /* Build configuration list for PBXNativeTarget "Firestore_IntegrationTests_macOS" */; buildPhases = ( - 8910A34006286584E91CC6DC /* [CP] Check Pods Manifest.lock */, + C5C547F6260A773F09E0CD27 /* [CP] Check Pods Manifest.lock */, 54B8E4A6224BDC4100930F18 /* Sources */, 54B8E4A7224BDC4100930F18 /* Frameworks */, 54B8E4A8224BDC4100930F18 /* Resources */, - 633674F5147FBB8C1FD5FEDD /* [CP] Embed Pods Frameworks */, + A52A1C613B3CE4DF90CBB478 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3480,11 +3482,11 @@ isa = PBXNativeTarget; buildConfigurationList = 5CAE132020FFFED600BE9A4A /* Build configuration list for PBXNativeTarget "Firestore_Benchmarks_iOS" */; buildPhases = ( - C68DD37C165D7B574ECBB922 /* [CP] Check Pods Manifest.lock */, + 41473C210CD4E5C6535B6884 /* [CP] Check Pods Manifest.lock */, 5CAE131520FFFED600BE9A4A /* Sources */, 5CAE131620FFFED600BE9A4A /* Frameworks */, 5CAE131720FFFED600BE9A4A /* Resources */, - B95E0392E921938AC60FCF25 /* [CP] Embed Pods Frameworks */, + CFAD6D72D505B2F5CE83289C /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3500,11 +3502,11 @@ isa = PBXNativeTarget; buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "Firestore_Example_iOS" */; buildPhases = ( - D597DC0C7CBDC9CBBF450EF9 /* [CP] Check Pods Manifest.lock */, + CA90036E973F54074940A15A /* [CP] Check Pods Manifest.lock */, 6003F586195388D20070C39A /* Sources */, 6003F587195388D20070C39A /* Frameworks */, 6003F588195388D20070C39A /* Resources */, - CAFA3F6E97C2D5C7FB66B9A7 /* [CP] Embed Pods Frameworks */, + 80BFE7E5486900E78F2BA5D8 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3519,11 +3521,11 @@ isa = PBXNativeTarget; buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Firestore_Tests_iOS" */; buildPhases = ( - 7F5E4B9C83AA91EFE162BF97 /* [CP] Check Pods Manifest.lock */, + 60B72D5F13F781972C5A5C0D /* [CP] Check Pods Manifest.lock */, 6003F5AA195388D20070C39A /* Sources */, 6003F5AB195388D20070C39A /* Frameworks */, 6003F5AC195388D20070C39A /* Resources */, - 3E49BD3598B1B6454C94341C /* [CP] Embed Pods Frameworks */, + 0BDCD61CAA07D5AFD01DC61E /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3558,11 +3560,11 @@ isa = PBXNativeTarget; buildConfigurationList = DAFF0D0521E64AC40062958F /* Build configuration list for PBXNativeTarget "Firestore_Example_macOS" */; buildPhases = ( - 11729AF0AA6C8C2719E12B93 /* [CP] Check Pods Manifest.lock */, + BED6B25C73028EA62E2D2965 /* [CP] Check Pods Manifest.lock */, DAFF0CF121E64AC30062958F /* Sources */, DAFF0CF221E64AC30062958F /* Frameworks */, DAFF0CF321E64AC30062958F /* Resources */, - 4AD644A1CEE1248C527E892A /* [CP] Embed Pods Frameworks */, + 83530587FE1C908EDF2F8F6F /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -3577,11 +3579,11 @@ isa = PBXNativeTarget; buildConfigurationList = DE03B2E61F2149D600A30B9C /* Build configuration list for PBXNativeTarget "Firestore_IntegrationTests_iOS" */; buildPhases = ( - CBADFCA235F8428F57C4F3E4 /* [CP] Check Pods Manifest.lock */, + 476B5F47386686F8AC664946 /* [CP] Check Pods Manifest.lock */, DE03B2981F2149D600A30B9C /* Sources */, DE03B2D31F2149D600A30B9C /* Frameworks */, DE03B2D81F2149D600A30B9C /* Resources */, - 23F727CA498241B895EF8577 /* [CP] Embed Pods Frameworks */, + 36A3BF669E405BF9F0C8B428 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -4032,29 +4034,22 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 11729AF0AA6C8C2719E12B93 /* [CP] Check Pods Manifest.lock */ = { + 0BDCD61CAA07D5AFD01DC61E /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_macOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 23F727CA498241B895EF8577 /* [CP] Embed Pods Frameworks */ = { + 36A3BF669E405BF9F0C8B428 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4069,37 +4064,51 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 3E49BD3598B1B6454C94341C /* [CP] Embed Pods Frameworks */ = { + 41473C210CD4E5C6535B6884 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Firestore_Benchmarks_iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 470F142676C51630881DE722 /* [CP] Embed Pods Frameworks */ = { + 476B5F47386686F8AC664946 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Firestore_IntegrationTests_iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 4AD644A1CEE1248C527E892A /* [CP] Embed Pods Frameworks */ = { + 49223B384693551711FF9FBF /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4111,10 +4120,10 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_macOS/Pods-Firestore_Tests_macOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 4BFF87BC6397E978B275C6A8 /* [CP] Check Pods Manifest.lock */ = { + 5EB3B73D994059115EE9E133 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4129,41 +4138,55 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_tvOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_tvOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 4EFCC40FAD4523014466B872 /* [CP] Embed Pods Frameworks */ = { + 60B72D5F13F781972C5A5C0D /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 633674F5147FBB8C1FD5FEDD /* [CP] Embed Pods Frameworks */ = { + 64F12822E1DB6C711C848A4C /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Firestore_IntegrationTests_tvOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 6E622C7A20F52C8300B7E93A /* Run Script */ = { @@ -4183,73 +4206,37 @@ shellScript = "\"${SRCROOT}/FuzzTests/FuzzingResources/Serializer/Corpus/ConvertTextToBinary.sh\""; showEnvVarsInLog = 0; }; - 7F5E4B9C83AA91EFE162BF97 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_iOS-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 8910A34006286584E91CC6DC /* [CP] Check Pods Manifest.lock */ = { + 80BFE7E5486900E78F2BA5D8 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_IntegrationTests_macOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 9924014786EA7DE18926B94C /* [CP] Check Pods Manifest.lock */ = { + 83530587FE1C908EDF2F8F6F /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_tvOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_macOS/Pods-Firestore_Example_macOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - B95E0392E921938AC60FCF25 /* [CP] Embed Pods Frameworks */ = { + 8C54C9D79238315A22209F10 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4261,10 +4248,10 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - BFA27F7A0A2F3791CC6AD5F3 /* [CP] Embed Pods Frameworks */ = { + A52A1C613B3CE4DF90CBB478 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4276,25 +4263,32 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - C28155D3E0ED2F6C48249B5F /* [CP] Embed Pods Frameworks */ = { + B63951B6F1AC344D56A285BB /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_macOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Tests_tvOS/Pods-Firestore_Tests_tvOS-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - C68DD37C165D7B574ECBB922 /* [CP] Check Pods Manifest.lock */ = { + B97602CD18E190159B0EA450 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4309,14 +4303,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Benchmarks_iOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_tvOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - C85CCD6E92EE34EA8E132CCC /* [CP] Check Pods Manifest.lock */ = { + BED6B25C73028EA62E2D2965 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4331,14 +4325,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_IntegrationTests_tvOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_macOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - CAFA3F6E97C2D5C7FB66B9A7 /* [CP] Embed Pods Frameworks */ = { + C0DB68EB86D2339FF6498AD5 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4350,10 +4344,10 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_IntegrationTests_tvOS/Pods-Firestore_IntegrationTests_tvOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - CBADFCA235F8428F57C4F3E4 /* [CP] Check Pods Manifest.lock */ = { + C5C547F6260A773F09E0CD27 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4368,14 +4362,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_IntegrationTests_iOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Firestore_IntegrationTests_macOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - D0E2864849F7821EA1766350 /* [CP] Check Pods Manifest.lock */ = { + CA90036E973F54074940A15A /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -4390,33 +4384,41 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Tests_macOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - D597DC0C7CBDC9CBBF450EF9 /* [CP] Check Pods Manifest.lock */ = { + CFAD6D72D505B2F5CE83289C /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Benchmarks_iOS/Pods-Firestore_Benchmarks_iOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + FCE4187347D5B0975354AC0D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( ); + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Firestore_Example_iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Firestore_Example_tvOS/Pods-Firestore_Example_tvOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -6137,7 +6139,7 @@ /* Begin XCBuildConfiguration section */ 544AB1992248072200F851E6 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4EAA1E2AC6B9AD4D3876C451 /* Pods-Firestore_Tests_macOS.debug.xcconfig */; + baseConfigurationReference = 921DD3C8DFD768101F11AE9E /* Pods-Firestore_Tests_macOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6161,7 +6163,7 @@ }; 544AB19A2248072200F851E6 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5DC11E3981B81DDFF8A4453B /* Pods-Firestore_Tests_macOS.release.xcconfig */; + baseConfigurationReference = 581E1E6A034002250995098C /* Pods-Firestore_Tests_macOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6187,7 +6189,7 @@ }; 54AA339F224BF936006CE580 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DFB2CD94DF4A37DCC987E3CC /* Pods-Firestore_Example_tvOS.debug.xcconfig */; + baseConfigurationReference = 36121362F78AB49532007335 /* Pods-Firestore_Example_tvOS.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; @@ -6210,7 +6212,7 @@ }; 54AA33A0224BF936006CE580 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 459864A45E38975067B09B19 /* Pods-Firestore_Example_tvOS.release.xcconfig */; + baseConfigurationReference = 324ACEF203B31D0C0C727635 /* Pods-Firestore_Example_tvOS.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; @@ -6234,7 +6236,7 @@ }; 54AA33AD224BFE0A006CE580 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = EC00431536EFDDE0256357E2 /* Pods-Firestore_Tests_tvOS.debug.xcconfig */; + baseConfigurationReference = 3764417D8A7C5DC5F07D4FAC /* Pods-Firestore_Tests_tvOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6256,7 +6258,7 @@ }; 54AA33AE224BFE0A006CE580 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F8222AA70B3B1CAA6CF73DE0 /* Pods-Firestore_Tests_tvOS.release.xcconfig */; + baseConfigurationReference = DB19B825EC1F2680D3D5F040 /* Pods-Firestore_Tests_tvOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6279,7 +6281,7 @@ }; 54AA33BC224C0035006CE580 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 765CEDF282B8255A337CEF80 /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */; + baseConfigurationReference = 1EA35EF4A5508688A82334C9 /* Pods-Firestore_IntegrationTests_tvOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6301,7 +6303,7 @@ }; 54AA33BD224C0035006CE580 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CC85FC848368E88FA264A1BE /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */; + baseConfigurationReference = 9D9E3DFC76D84FC2554F47B3 /* Pods-Firestore_IntegrationTests_tvOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6324,7 +6326,7 @@ }; 54B8E4B1224BDC4100930F18 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9DE6467395E0973563A0BF9D /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */; + baseConfigurationReference = 8696B66E66E4C8B036459A5E /* Pods-Firestore_IntegrationTests_macOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6348,7 +6350,7 @@ }; 54B8E4B2224BDC4100930F18 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 319C19479B01F7DEEAD9774A /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */; + baseConfigurationReference = E6F6E872A9615A88736EACB7 /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -6373,7 +6375,7 @@ }; 5CAE132120FFFED600BE9A4A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F1F1CCCF68677C413FEFB2BC /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */; + baseConfigurationReference = 90D3C05AE151D47E2CAF3758 /* Pods-Firestore_Benchmarks_iOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; @@ -6387,7 +6389,7 @@ }; 5CAE132220FFFED600BE9A4A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 04F95FB0B1123006B5DA8153 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */; + baseConfigurationReference = 4D1A32406F36DE4ACF604E93 /* Pods-Firestore_Benchmarks_iOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; @@ -6510,7 +6512,7 @@ }; 6003F5C0195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BD030C308116480114144B89 /* Pods-Firestore_Example_iOS.debug.xcconfig */; + baseConfigurationReference = 06D1849DBC8EB170168B7FBA /* Pods-Firestore_Example_iOS.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -6532,7 +6534,7 @@ }; 6003F5C1195388D20070C39A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 20C55A10362C9BDE9FB8C5E1 /* Pods-Firestore_Example_iOS.release.xcconfig */; + baseConfigurationReference = 2565B04EF9072C15071E0FB3 /* Pods-Firestore_Example_iOS.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -6554,7 +6556,7 @@ }; 6003F5C3195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4BB169579995C73A8BF4D981 /* Pods-Firestore_Tests_iOS.debug.xcconfig */; + baseConfigurationReference = B9E41EFAB22DF1E7B475AE96 /* Pods-Firestore_Tests_iOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; @@ -6615,7 +6617,7 @@ }; 6003F5C4195388D20070C39A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DE9C9075C63C66F01961750F /* Pods-Firestore_Tests_iOS.release.xcconfig */; + baseConfigurationReference = F8667425B6A18A7C98124FEF /* Pods-Firestore_Tests_iOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; @@ -6704,7 +6706,7 @@ }; DAFF0D0321E64AC40062958F /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6ABFEF8FB2361EEE737CB120 /* Pods-Firestore_Example_macOS.debug.xcconfig */; + baseConfigurationReference = 6AC7F3A6784E9FAE5E15D082 /* Pods-Firestore_Example_macOS.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; @@ -6741,7 +6743,7 @@ }; DAFF0D0421E64AC40062958F /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6CA462CE027855D254A69006 /* Pods-Firestore_Example_macOS.release.xcconfig */; + baseConfigurationReference = A1439162E5B5C2C81A2BCB02 /* Pods-Firestore_Example_macOS.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; @@ -6779,7 +6781,7 @@ }; DE03B2E71F2149D600A30B9C /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 831CE94805EAC3F88B9019DA /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */; + baseConfigurationReference = 7054E3FD979D9C8E870DB6BB /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; @@ -6804,7 +6806,7 @@ }; DE03B2E81F2149D600A30B9C /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8DB38D2B14D3955ACA3F3952 /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */; + baseConfigurationReference = 920E8C520B88EA78346BB86D /* Pods-Firestore_IntegrationTests_iOS.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = EQHXZ8M8AV; diff --git a/Firestore/core/CMakeLists.txt b/Firestore/core/CMakeLists.txt index 8971b7cd965..4591fb7e2dd 100644 --- a/Firestore/core/CMakeLists.txt +++ b/Firestore/core/CMakeLists.txt @@ -200,26 +200,26 @@ firebase_ios_glob( src/bundle/*.h src/core/*.cc src/core/*.h - src/core/pipeline/*.cc - src/core/pipeline/*.h - src/core/pipeline/evaluation/arithmetic.cc - src/core/pipeline/evaluation/arithmetic.h - src/core/pipeline/evaluation/array.cc - src/core/pipeline/evaluation/array.h - src/core/pipeline/evaluation/comparison.cc - src/core/pipeline/evaluation/comparison.h - src/core/pipeline/evaluation/logical.cc - src/core/pipeline/evaluation/logical.h - src/core/pipeline/evaluation/map.cc - src/core/pipeline/evaluation/map.h - src/core/pipeline/evaluation/string.cc - src/core/pipeline/evaluation/string.h - src/core/pipeline/evaluation/timestamp.cc - src/core/pipeline/evaluation/timestamp.h - src/core/pipeline/evaluation/type.cc - src/core/pipeline/evaluation/type.h - src/core/pipeline/evaluation/util.cc - src/core/pipeline/evaluation/util.h + src/pipeline/*.cc + src/pipeline/*.h + src/pipeline/arithmetic_evaluation.cc + src/pipeline/arithmetic_evaluation.h + src/pipeline/array_evaluation.cc + src/pipeline/array_evaluation.h + src/pipeline/comparison_evaluation.cc + src/pipeline/comparison_evaluation.h + src/pipeline/logical_evaluation.cc + src/pipeline/logical_evaluation.h + src/pipeline/map_evaluation.cc + src/pipeline/map_evaluation.h + src/pipeline/string_evaluation.cc + src/pipeline/string_evaluation.h + src/pipeline/timestamp_evaluation.cc + src/pipeline/timestamp_evaluation.h + src/pipeline/type_evaluation.cc + src/pipeline/type_evaluation.h + src/pipeline/util_evaluation.cc + src/pipeline/util_evaluation.h src/credentials/*.cc src/credentials/*.h src/immutable/*.cc @@ -263,7 +263,7 @@ target_compile_definitions( target_include_directories( firestore_core PUBLIC ${PROJECT_SOURCE_DIR}/Firestore/core/include - ${PROJECT_SOURCE_DIR}/Firestore/core/src/core + ${PROJECT_SOURCE_DIR}/Firestore/core/src ) # Add the gRPC include directories as SYSTEM directories to silence warnings diff --git a/Firestore/core/src/api/expressions.cc b/Firestore/core/src/api/expressions.cc index 8fcb86ec81a..8f44800d846 100644 --- a/Firestore/core/src/api/expressions.cc +++ b/Firestore/core/src/api/expressions.cc @@ -19,7 +19,7 @@ #include #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/nanopb/nanopb_util.h" diff --git a/Firestore/core/src/api/stages.cc b/Firestore/core/src/api/stages.cc index 5a9eab28687..656c53ff6d9 100644 --- a/Firestore/core/src/api/stages.cc +++ b/Firestore/core/src/api/stages.cc @@ -25,7 +25,7 @@ #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" #include "Firestore/core/src/api/pipeline.h" -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/model/document_key.h" #include "Firestore/core/src/model/mutable_document.h" #include "Firestore/core/src/model/resource_path.h" diff --git a/Firestore/core/src/core/pipeline_util.cc b/Firestore/core/src/core/pipeline_util.cc index c9db008f9b0..a4840e22910 100644 --- a/Firestore/core/src/core/pipeline_util.cc +++ b/Firestore/core/src/core/pipeline_util.cc @@ -26,7 +26,7 @@ #include "Firestore/core/src/api/realtime_pipeline.h" #include "Firestore/core/src/api/stages.h" #include "Firestore/core/src/core/bound.h" -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/core/pipeline_run.h" #include "Firestore/core/src/core/query.h" #include "Firestore/core/src/model/document_set.h" diff --git a/Firestore/core/src/core/pipeline/aggregates_evaluation.cc b/Firestore/core/src/pipeline/aggregates_evaluation.cc similarity index 97% rename from Firestore/core/src/core/pipeline/aggregates_evaluation.cc rename to Firestore/core/src/pipeline/aggregates_evaluation.cc index 2e0bc1d29ab..bea91a2cb22 100644 --- a/Firestore/core/src/core/pipeline/aggregates_evaluation.cc +++ b/Firestore/core/src/pipeline/aggregates_evaluation.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/aggregates_evaluation.h" +#include "Firestore/core/src/pipeline/aggregates_evaluation.h" #include diff --git a/Firestore/core/src/core/pipeline/aggregates_evaluation.h b/Firestore/core/src/pipeline/aggregates_evaluation.h similarity index 96% rename from Firestore/core/src/core/pipeline/aggregates_evaluation.h rename to Firestore/core/src/pipeline/aggregates_evaluation.h index 933c53f4e74..921bf13c1d6 100644 --- a/Firestore/core/src/core/pipeline/aggregates_evaluation.h +++ b/Firestore/core/src/pipeline/aggregates_evaluation.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_EVALUATION_H_ #include -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/arithmetic.cc b/Firestore/core/src/pipeline/arithmetic_evaluation.cc similarity index 98% rename from Firestore/core/src/core/pipeline/evaluation/arithmetic.cc rename to Firestore/core/src/pipeline/arithmetic_evaluation.cc index 9f3c4e0641e..09ebff05943 100644 --- a/Firestore/core/src/core/pipeline/evaluation/arithmetic.cc +++ b/Firestore/core/src/pipeline/arithmetic_evaluation.cc @@ -14,13 +14,13 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/evaluation/arithmetic.h" +#include "Firestore/core/src/pipeline/arithmetic_evaluation.h" #include #include #include -#include "Firestore/core/src/core/pipeline/evaluation/util.h" +#include "Firestore/core/src/pipeline/util_evaluation.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/util/hard_assert.h" #include "absl/types/optional.h" diff --git a/Firestore/core/src/core/pipeline/evaluation/arithmetic.h b/Firestore/core/src/pipeline/arithmetic_evaluation.h similarity index 98% rename from Firestore/core/src/core/pipeline/evaluation/arithmetic.h rename to Firestore/core/src/pipeline/arithmetic_evaluation.h index 53640181584..03cd2960295 100644 --- a/Firestore/core/src/core/pipeline/evaluation/arithmetic.h +++ b/Firestore/core/src/pipeline/arithmetic_evaluation.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARITHMETIC_H_ #include -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/array.cc b/Firestore/core/src/pipeline/array_evaluation.cc similarity index 98% rename from Firestore/core/src/core/pipeline/evaluation/array.cc rename to Firestore/core/src/pipeline/array_evaluation.cc index 96ec187e5e2..c850dcf35b7 100644 --- a/Firestore/core/src/core/pipeline/evaluation/array.cc +++ b/Firestore/core/src/pipeline/array_evaluation.cc @@ -14,15 +14,15 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/evaluation/array.h" +#include "Firestore/core/src/pipeline/array_evaluation.h" #include #include #include #include -#include "Firestore/core/src/core/pipeline/evaluation/logical.h" -#include "Firestore/core/src/core/pipeline/evaluation/util.h" +#include "Firestore/core/src/pipeline/logical_evaluation.h" +#include "Firestore/core/src/pipeline/util_evaluation.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/util/hard_assert.h" diff --git a/Firestore/core/src/core/pipeline/evaluation/array.h b/Firestore/core/src/pipeline/array_evaluation.h similarity index 97% rename from Firestore/core/src/core/pipeline/evaluation/array.h rename to Firestore/core/src/pipeline/array_evaluation.h index 397b54a5097..d8d64aff123 100644 --- a/Firestore/core/src/core/pipeline/evaluation/array.h +++ b/Firestore/core/src/pipeline/array_evaluation.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARRAY_H_ #include -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/comparison.cc b/Firestore/core/src/pipeline/comparison_evaluation.cc similarity index 99% rename from Firestore/core/src/core/pipeline/evaluation/comparison.cc rename to Firestore/core/src/pipeline/comparison_evaluation.cc index eed478779df..481fa5983b6 100644 --- a/Firestore/core/src/core/pipeline/evaluation/comparison.cc +++ b/Firestore/core/src/pipeline/comparison_evaluation.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/evaluation/comparison.h" +#include "Firestore/core/src/pipeline/comparison_evaluation.h" #include #include "Firestore/core/src/model/value_util.h" diff --git a/Firestore/core/src/core/pipeline/evaluation/comparison.h b/Firestore/core/src/pipeline/comparison_evaluation.h similarity index 98% rename from Firestore/core/src/core/pipeline/evaluation/comparison.h rename to Firestore/core/src/pipeline/comparison_evaluation.h index 23d6ac8e512..ccf517d9de6 100644 --- a/Firestore/core/src/core/pipeline/evaluation/comparison.h +++ b/Firestore/core/src/pipeline/comparison_evaluation.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_COMPARISON_H_ #include -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/expression_evaluation.cc b/Firestore/core/src/pipeline/expression_evaluation.cc similarity index 94% rename from Firestore/core/src/core/pipeline/expression_evaluation.cc rename to Firestore/core/src/pipeline/expression_evaluation.cc index ebe786fb409..d9abde03494 100644 --- a/Firestore/core/src/core/pipeline/expression_evaluation.cc +++ b/Firestore/core/src/pipeline/expression_evaluation.cc @@ -14,20 +14,20 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" #include #include // For std::move -#include "Firestore/core/src/core/pipeline/aggregates_evaluation.h" -#include "Firestore/core/src/core/pipeline/evaluation/arithmetic.h" -#include "Firestore/core/src/core/pipeline/evaluation/array.h" -#include "Firestore/core/src/core/pipeline/evaluation/comparison.h" -#include "Firestore/core/src/core/pipeline/evaluation/logical.h" -#include "Firestore/core/src/core/pipeline/evaluation/map.h" -#include "Firestore/core/src/core/pipeline/evaluation/string.h" -#include "Firestore/core/src/core/pipeline/evaluation/timestamp.h" -#include "Firestore/core/src/core/pipeline/evaluation/type.h" +#include "Firestore/core/src/pipeline/aggregates_evaluation.h" +#include "Firestore/core/src/pipeline/arithmetic_evaluation.h" +#include "Firestore/core/src/pipeline/array_evaluation.h" +#include "Firestore/core/src/pipeline/comparison_evaluation.h" +#include "Firestore/core/src/pipeline/logical_evaluation.h" +#include "Firestore/core/src/pipeline/map_evaluation.h" +#include "Firestore/core/src/pipeline/string_evaluation.h" +#include "Firestore/core/src/pipeline/timestamp_evaluation.h" +#include "Firestore/core/src/pipeline/type_evaluation.h" #include "Firestore/core/src/model/mutable_document.h" #include "Firestore/core/src/model/server_timestamp_util.h" #include "Firestore/core/src/model/value_util.h" diff --git a/Firestore/core/src/core/pipeline/expression_evaluation.h b/Firestore/core/src/pipeline/expression_evaluation.h similarity index 100% rename from Firestore/core/src/core/pipeline/expression_evaluation.h rename to Firestore/core/src/pipeline/expression_evaluation.h diff --git a/Firestore/core/src/core/pipeline/evaluation/logical.cc b/Firestore/core/src/pipeline/logical_evaluation.cc similarity index 99% rename from Firestore/core/src/core/pipeline/evaluation/logical.cc rename to Firestore/core/src/pipeline/logical_evaluation.cc index 4e859595e04..50ae7483fd3 100644 --- a/Firestore/core/src/core/pipeline/evaluation/logical.cc +++ b/Firestore/core/src/pipeline/logical_evaluation.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/evaluation/logical.h" +#include "Firestore/core/src/pipeline/logical_evaluation.h" #include #include diff --git a/Firestore/core/src/core/pipeline/evaluation/logical.h b/Firestore/core/src/pipeline/logical_evaluation.h similarity index 98% rename from Firestore/core/src/core/pipeline/evaluation/logical.h rename to Firestore/core/src/pipeline/logical_evaluation.h index 597accca9c8..2fb39d9b11a 100644 --- a/Firestore/core/src/core/pipeline/evaluation/logical.h +++ b/Firestore/core/src/pipeline/logical_evaluation.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_LOGICAL_H_ #include -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/map.cc b/Firestore/core/src/pipeline/map_evaluation.cc similarity index 97% rename from Firestore/core/src/core/pipeline/evaluation/map.cc rename to Firestore/core/src/pipeline/map_evaluation.cc index 75a4b9c9285..b923dad860a 100644 --- a/Firestore/core/src/core/pipeline/evaluation/map.cc +++ b/Firestore/core/src/pipeline/map_evaluation.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/evaluation/map.h" +#include "Firestore/core/src/pipeline/map_evaluation.h" #include #include diff --git a/Firestore/core/src/core/pipeline/evaluation/map.h b/Firestore/core/src/pipeline/map_evaluation.h similarity index 95% rename from Firestore/core/src/core/pipeline/evaluation/map.h rename to Firestore/core/src/pipeline/map_evaluation.h index 4946f2cf6f5..f4ea4b18614 100644 --- a/Firestore/core/src/core/pipeline/evaluation/map.h +++ b/Firestore/core/src/pipeline/map_evaluation.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_MAP_H_ #include -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/string.cc b/Firestore/core/src/pipeline/string_evaluation.cc similarity index 99% rename from Firestore/core/src/core/pipeline/evaluation/string.cc rename to Firestore/core/src/pipeline/string_evaluation.cc index 65db0b58d8c..9a6f7665981 100644 --- a/Firestore/core/src/core/pipeline/evaluation/string.cc +++ b/Firestore/core/src/pipeline/string_evaluation.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/evaluation/string.h" +#include "Firestore/core/src/pipeline/string_evaluation.h" #include #include @@ -23,7 +23,7 @@ #include #include -#include "Firestore/core/src/core/pipeline/evaluation/util.h" +#include "Firestore/core/src/pipeline/util_evaluation.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/util/hard_assert.h" #include "absl/strings/match.h" diff --git a/Firestore/core/src/core/pipeline/evaluation/string.h b/Firestore/core/src/pipeline/string_evaluation.h similarity index 98% rename from Firestore/core/src/core/pipeline/evaluation/string.h rename to Firestore/core/src/pipeline/string_evaluation.h index 8c7cd1b78ee..181b986d0e5 100644 --- a/Firestore/core/src/core/pipeline/evaluation/string.h +++ b/Firestore/core/src/pipeline/string_evaluation.h @@ -19,7 +19,7 @@ #include #include -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/timestamp.cc b/Firestore/core/src/pipeline/timestamp_evaluation.cc similarity index 98% rename from Firestore/core/src/core/pipeline/evaluation/timestamp.cc rename to Firestore/core/src/pipeline/timestamp_evaluation.cc index 2748a3b057d..2312ca65883 100644 --- a/Firestore/core/src/core/pipeline/evaluation/timestamp.cc +++ b/Firestore/core/src/pipeline/timestamp_evaluation.cc @@ -14,11 +14,11 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/evaluation/timestamp.h" +#include "Firestore/core/src/pipeline/timestamp_evaluation.h" #include -#include "Firestore/core/src/core/pipeline/evaluation/util.h" +#include "Firestore/core/src/pipeline/util_evaluation.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/util/hard_assert.h" #include "absl/strings/string_view.h" diff --git a/Firestore/core/src/core/pipeline/evaluation/timestamp.h b/Firestore/core/src/pipeline/timestamp_evaluation.h similarity index 98% rename from Firestore/core/src/core/pipeline/evaluation/timestamp.h rename to Firestore/core/src/pipeline/timestamp_evaluation.h index e5561152128..5b5dc9a2321 100644 --- a/Firestore/core/src/core/pipeline/evaluation/timestamp.h +++ b/Firestore/core/src/pipeline/timestamp_evaluation.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TIMESTAMP_H_ #include -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/type.cc b/Firestore/core/src/pipeline/type_evaluation.cc similarity index 97% rename from Firestore/core/src/core/pipeline/evaluation/type.cc rename to Firestore/core/src/pipeline/type_evaluation.cc index 9782ea457b1..1ae4d20fb1d 100644 --- a/Firestore/core/src/core/pipeline/evaluation/type.cc +++ b/Firestore/core/src/pipeline/type_evaluation.cc @@ -14,8 +14,8 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/evaluation/type.h" -#include "Firestore/core/src/core/pipeline/evaluation/logical.h" +#include "Firestore/core/src/pipeline/type_evaluation.h" +#include "Firestore/core/src/pipeline/logical_evaluation.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/util/hard_assert.h" diff --git a/Firestore/core/src/core/pipeline/evaluation/type.h b/Firestore/core/src/pipeline/type_evaluation.h similarity index 97% rename from Firestore/core/src/core/pipeline/evaluation/type.h rename to Firestore/core/src/pipeline/type_evaluation.h index a16635e1f18..86d431dd1d6 100644 --- a/Firestore/core/src/core/pipeline/evaluation/type.h +++ b/Firestore/core/src/pipeline/type_evaluation.h @@ -18,7 +18,7 @@ #define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TYPE_H_ #include -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/core/pipeline/evaluation/util.cc b/Firestore/core/src/pipeline/util_evaluation.cc similarity index 97% rename from Firestore/core/src/core/pipeline/evaluation/util.cc rename to Firestore/core/src/pipeline/util_evaluation.cc index ac9aa45848e..1b5a9076c99 100644 --- a/Firestore/core/src/core/pipeline/evaluation/util.cc +++ b/Firestore/core/src/pipeline/util_evaluation.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "Firestore/core/src/core/pipeline/evaluation/util.h" +#include "Firestore/core/src/pipeline/util_evaluation.h" #include #include diff --git a/Firestore/core/src/core/pipeline/evaluation/util.h b/Firestore/core/src/pipeline/util_evaluation.h similarity index 100% rename from Firestore/core/src/core/pipeline/evaluation/util.h rename to Firestore/core/src/pipeline/util_evaluation.h diff --git a/Firestore/core/test/unit/core/expressions/arithmetic_test.cc b/Firestore/core/test/unit/core/expressions/arithmetic_test.cc index 4465236835b..3496dbe4e82 100644 --- a/Firestore/core/test/unit/core/expressions/arithmetic_test.cc +++ b/Firestore/core/test/unit/core/expressions/arithmetic_test.cc @@ -17,7 +17,7 @@ #include #include -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/test/unit/testutil/expression_test_util.h" #include "Firestore/core/test/unit/testutil/testutil.h" #include "gmock/gmock.h" diff --git a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc index 975b0c4a892..4f70a0157d2 100644 --- a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc +++ b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc @@ -21,7 +21,7 @@ #include #include "Firestore/core/src/api/expressions.h" -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/model/field_path.h" #include "Firestore/core/src/util/string_format.h" #include "Firestore/core/test/unit/testutil/expression_test_util.h" diff --git a/Firestore/core/test/unit/testutil/expression_test_util.h b/Firestore/core/test/unit/testutil/expression_test_util.h index fe4568d56b9..62b64773e54 100644 --- a/Firestore/core/test/unit/testutil/expression_test_util.h +++ b/Firestore/core/test/unit/testutil/expression_test_util.h @@ -30,16 +30,16 @@ #include "Firestore/core/include/firebase/firestore/timestamp.h" #include "Firestore/core/src/api/expressions.h" #include "Firestore/core/src/api/stages.h" -#include "Firestore/core/src/core/pipeline/aggregates_evaluation.h" -#include "Firestore/core/src/core/pipeline/evaluation/arithmetic.h" -#include "Firestore/core/src/core/pipeline/evaluation/array.h" -#include "Firestore/core/src/core/pipeline/evaluation/comparison.h" -#include "Firestore/core/src/core/pipeline/evaluation/logical.h" -#include "Firestore/core/src/core/pipeline/evaluation/map.h" -#include "Firestore/core/src/core/pipeline/evaluation/string.h" -#include "Firestore/core/src/core/pipeline/evaluation/timestamp.h" -#include "Firestore/core/src/core/pipeline/evaluation/type.h" -#include "Firestore/core/src/core/pipeline/expression_evaluation.h" +#include "Firestore/core/src/pipeline/aggregates_evaluation.h" +#include "Firestore/core/src/pipeline/arithmetic_evaluation.h" +#include "Firestore/core/src/pipeline/array_evaluation.h" +#include "Firestore/core/src/pipeline/comparison_evaluation.h" +#include "Firestore/core/src/pipeline/logical_evaluation.h" +#include "Firestore/core/src/pipeline/map_evaluation.h" +#include "Firestore/core/src/pipeline/string_evaluation.h" +#include "Firestore/core/src/pipeline/timestamp_evaluation.h" +#include "Firestore/core/src/pipeline/type_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/model/database_id.h" #include "Firestore/core/src/model/document_key.h" #include "Firestore/core/src/model/mutable_document.h" From ce09700172b835df8a93ac9a284d718b0f143999 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 3 Dec 2025 11:55:44 -0500 Subject: [PATCH 33/36] simplify cmake file --- Firestore/core/CMakeLists.txt | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/Firestore/core/CMakeLists.txt b/Firestore/core/CMakeLists.txt index 4591fb7e2dd..7ada668d043 100644 --- a/Firestore/core/CMakeLists.txt +++ b/Firestore/core/CMakeLists.txt @@ -202,24 +202,6 @@ firebase_ios_glob( src/core/*.h src/pipeline/*.cc src/pipeline/*.h - src/pipeline/arithmetic_evaluation.cc - src/pipeline/arithmetic_evaluation.h - src/pipeline/array_evaluation.cc - src/pipeline/array_evaluation.h - src/pipeline/comparison_evaluation.cc - src/pipeline/comparison_evaluation.h - src/pipeline/logical_evaluation.cc - src/pipeline/logical_evaluation.h - src/pipeline/map_evaluation.cc - src/pipeline/map_evaluation.h - src/pipeline/string_evaluation.cc - src/pipeline/string_evaluation.h - src/pipeline/timestamp_evaluation.cc - src/pipeline/timestamp_evaluation.h - src/pipeline/type_evaluation.cc - src/pipeline/type_evaluation.h - src/pipeline/util_evaluation.cc - src/pipeline/util_evaluation.h src/credentials/*.cc src/credentials/*.h src/immutable/*.cc From f95b2f031c19f4fac310ff038fe677a634547f72 Mon Sep 17 00:00:00 2001 From: cherylEnkidu <96084918+cherylEnkidu@users.noreply.github.com> Date: Wed, 3 Dec 2025 12:46:53 -0500 Subject: [PATCH 34/36] Update Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift b/Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift index df78858175e..120a4a6c642 100644 --- a/Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift +++ b/Firestore/Swift/Tests/Integration/RealtimePipelineTests.swift @@ -590,7 +590,7 @@ class RealtimePipelineIntegrationTests: FSTIntegrationTestCase { // enableNetwork() } - func testSamePipelineWithDifferetnOptions() async throws { + func testSamePipelineWithDifferentOptions() async throws { let db = self.db let collRef = collectionRef() writeAllDocuments(bookDocs, toCollection: collRef) From 03f5f07a0ad6235f377e5af5d4247d2942845b64 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 3 Dec 2025 13:49:10 -0500 Subject: [PATCH 35/36] format code --- Firestore/core/src/api/expressions.cc | 2 +- Firestore/core/src/api/stages.cc | 2 +- Firestore/core/src/core/pipeline_util.cc | 2 +- .../core/src/pipeline/arithmetic_evaluation.cc | 2 +- Firestore/core/src/pipeline/array_evaluation.cc | 2 +- .../core/src/pipeline/expression_evaluation.cc | 8 ++++---- Firestore/core/src/pipeline/string_evaluation.cc | 2 +- .../core/src/pipeline/timestamp_evaluation.cc | 2 +- Firestore/core/src/pipeline/type_evaluation.cc | 2 +- .../core/expressions/mirroring_semantics_test.cc | 2 +- .../test/unit/testutil/expression_test_util.h | 16 ++++++++-------- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Firestore/core/src/api/expressions.cc b/Firestore/core/src/api/expressions.cc index 8f44800d846..1c8f504b31c 100644 --- a/Firestore/core/src/api/expressions.cc +++ b/Firestore/core/src/api/expressions.cc @@ -19,9 +19,9 @@ #include #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" -#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/nanopb/nanopb_util.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" namespace firebase { namespace firestore { diff --git a/Firestore/core/src/api/stages.cc b/Firestore/core/src/api/stages.cc index 656c53ff6d9..11025e38786 100644 --- a/Firestore/core/src/api/stages.cc +++ b/Firestore/core/src/api/stages.cc @@ -25,12 +25,12 @@ #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" #include "Firestore/core/src/api/pipeline.h" -#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/model/document_key.h" #include "Firestore/core/src/model/mutable_document.h" #include "Firestore/core/src/model/resource_path.h" #include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/nanopb/nanopb_util.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/util/comparison.h" #include "Firestore/core/src/util/hard_assert.h" diff --git a/Firestore/core/src/core/pipeline_util.cc b/Firestore/core/src/core/pipeline_util.cc index a4840e22910..337a2a76ebf 100644 --- a/Firestore/core/src/core/pipeline_util.cc +++ b/Firestore/core/src/core/pipeline_util.cc @@ -26,11 +26,11 @@ #include "Firestore/core/src/api/realtime_pipeline.h" #include "Firestore/core/src/api/stages.h" #include "Firestore/core/src/core/bound.h" -#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/core/pipeline_run.h" #include "Firestore/core/src/core/query.h" #include "Firestore/core/src/model/document_set.h" #include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/util/comparison.h" #include "Firestore/core/src/util/exception.h" #include "Firestore/core/src/util/hard_assert.h" diff --git a/Firestore/core/src/pipeline/arithmetic_evaluation.cc b/Firestore/core/src/pipeline/arithmetic_evaluation.cc index 09ebff05943..00180d5e3b2 100644 --- a/Firestore/core/src/pipeline/arithmetic_evaluation.cc +++ b/Firestore/core/src/pipeline/arithmetic_evaluation.cc @@ -20,8 +20,8 @@ #include #include -#include "Firestore/core/src/pipeline/util_evaluation.h" #include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/pipeline/util_evaluation.h" #include "Firestore/core/src/util/hard_assert.h" #include "absl/types/optional.h" diff --git a/Firestore/core/src/pipeline/array_evaluation.cc b/Firestore/core/src/pipeline/array_evaluation.cc index c850dcf35b7..3b3723b045b 100644 --- a/Firestore/core/src/pipeline/array_evaluation.cc +++ b/Firestore/core/src/pipeline/array_evaluation.cc @@ -21,9 +21,9 @@ #include #include +#include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/pipeline/logical_evaluation.h" #include "Firestore/core/src/pipeline/util_evaluation.h" -#include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/util/hard_assert.h" namespace firebase { diff --git a/Firestore/core/src/pipeline/expression_evaluation.cc b/Firestore/core/src/pipeline/expression_evaluation.cc index d9abde03494..8f738bfca98 100644 --- a/Firestore/core/src/pipeline/expression_evaluation.cc +++ b/Firestore/core/src/pipeline/expression_evaluation.cc @@ -19,6 +19,10 @@ #include #include // For std::move +#include "Firestore/core/src/model/mutable_document.h" +#include "Firestore/core/src/model/server_timestamp_util.h" +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/nanopb/message.h" #include "Firestore/core/src/pipeline/aggregates_evaluation.h" #include "Firestore/core/src/pipeline/arithmetic_evaluation.h" #include "Firestore/core/src/pipeline/array_evaluation.h" @@ -28,10 +32,6 @@ #include "Firestore/core/src/pipeline/string_evaluation.h" #include "Firestore/core/src/pipeline/timestamp_evaluation.h" #include "Firestore/core/src/pipeline/type_evaluation.h" -#include "Firestore/core/src/model/mutable_document.h" -#include "Firestore/core/src/model/server_timestamp_util.h" -#include "Firestore/core/src/model/value_util.h" -#include "Firestore/core/src/nanopb/message.h" #include "Firestore/core/src/remote/serializer.h" #include "Firestore/core/src/util/hard_assert.h" diff --git a/Firestore/core/src/pipeline/string_evaluation.cc b/Firestore/core/src/pipeline/string_evaluation.cc index 9a6f7665981..676d4c93e0f 100644 --- a/Firestore/core/src/pipeline/string_evaluation.cc +++ b/Firestore/core/src/pipeline/string_evaluation.cc @@ -23,8 +23,8 @@ #include #include -#include "Firestore/core/src/pipeline/util_evaluation.h" #include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/pipeline/util_evaluation.h" #include "Firestore/core/src/util/hard_assert.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" diff --git a/Firestore/core/src/pipeline/timestamp_evaluation.cc b/Firestore/core/src/pipeline/timestamp_evaluation.cc index 2312ca65883..99b69a8e4e0 100644 --- a/Firestore/core/src/pipeline/timestamp_evaluation.cc +++ b/Firestore/core/src/pipeline/timestamp_evaluation.cc @@ -18,8 +18,8 @@ #include -#include "Firestore/core/src/pipeline/util_evaluation.h" #include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/pipeline/util_evaluation.h" #include "Firestore/core/src/util/hard_assert.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" diff --git a/Firestore/core/src/pipeline/type_evaluation.cc b/Firestore/core/src/pipeline/type_evaluation.cc index 1ae4d20fb1d..7673f9273dd 100644 --- a/Firestore/core/src/pipeline/type_evaluation.cc +++ b/Firestore/core/src/pipeline/type_evaluation.cc @@ -15,8 +15,8 @@ */ #include "Firestore/core/src/pipeline/type_evaluation.h" -#include "Firestore/core/src/pipeline/logical_evaluation.h" #include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/pipeline/logical_evaluation.h" #include "Firestore/core/src/util/hard_assert.h" namespace firebase { diff --git a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc index 4f70a0157d2..993294ead46 100644 --- a/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc +++ b/Firestore/core/test/unit/core/expressions/mirroring_semantics_test.cc @@ -21,8 +21,8 @@ #include #include "Firestore/core/src/api/expressions.h" -#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/model/field_path.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/util/string_format.h" #include "Firestore/core/test/unit/testutil/expression_test_util.h" #include "Firestore/core/test/unit/testutil/testutil.h" diff --git a/Firestore/core/test/unit/testutil/expression_test_util.h b/Firestore/core/test/unit/testutil/expression_test_util.h index 62b64773e54..cef812ef1a1 100644 --- a/Firestore/core/test/unit/testutil/expression_test_util.h +++ b/Firestore/core/test/unit/testutil/expression_test_util.h @@ -30,23 +30,23 @@ #include "Firestore/core/include/firebase/firestore/timestamp.h" #include "Firestore/core/src/api/expressions.h" #include "Firestore/core/src/api/stages.h" +#include "Firestore/core/src/model/database_id.h" +#include "Firestore/core/src/model/document_key.h" +#include "Firestore/core/src/model/mutable_document.h" +#include "Firestore/core/src/model/object_value.h" +#include "Firestore/core/src/model/snapshot_version.h" +#include "Firestore/core/src/model/value_util.h" +#include "Firestore/core/src/nanopb/message.h" #include "Firestore/core/src/pipeline/aggregates_evaluation.h" #include "Firestore/core/src/pipeline/arithmetic_evaluation.h" #include "Firestore/core/src/pipeline/array_evaluation.h" #include "Firestore/core/src/pipeline/comparison_evaluation.h" +#include "Firestore/core/src/pipeline/expression_evaluation.h" #include "Firestore/core/src/pipeline/logical_evaluation.h" #include "Firestore/core/src/pipeline/map_evaluation.h" #include "Firestore/core/src/pipeline/string_evaluation.h" #include "Firestore/core/src/pipeline/timestamp_evaluation.h" #include "Firestore/core/src/pipeline/type_evaluation.h" -#include "Firestore/core/src/pipeline/expression_evaluation.h" -#include "Firestore/core/src/model/database_id.h" -#include "Firestore/core/src/model/document_key.h" -#include "Firestore/core/src/model/mutable_document.h" -#include "Firestore/core/src/model/object_value.h" -#include "Firestore/core/src/model/snapshot_version.h" -#include "Firestore/core/src/model/value_util.h" -#include "Firestore/core/src/nanopb/message.h" #include "Firestore/core/src/remote/serializer.h" #include "Firestore/core/src/util/hard_assert.h" #include "Firestore/core/src/util/string_format.h" From d38b678588c327b78355da348a02e881054deafa Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 3 Dec 2025 14:28:09 -0500 Subject: [PATCH 36/36] fix header --- Firestore/core/src/pipeline/aggregates_evaluation.h | 6 +++--- Firestore/core/src/pipeline/arithmetic_evaluation.h | 6 +++--- Firestore/core/src/pipeline/array_evaluation.h | 6 +++--- Firestore/core/src/pipeline/comparison_evaluation.h | 6 +++--- Firestore/core/src/pipeline/expression_evaluation.h | 6 +++--- Firestore/core/src/pipeline/logical_evaluation.h | 6 +++--- Firestore/core/src/pipeline/map_evaluation.h | 6 +++--- Firestore/core/src/pipeline/string_evaluation.h | 6 +++--- Firestore/core/src/pipeline/timestamp_evaluation.h | 6 +++--- Firestore/core/src/pipeline/type_evaluation.h | 6 +++--- Firestore/core/src/pipeline/util_evaluation.h | 6 +++--- 11 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Firestore/core/src/pipeline/aggregates_evaluation.h b/Firestore/core/src/pipeline/aggregates_evaluation.h index 921bf13c1d6..b945519a00b 100644 --- a/Firestore/core/src/pipeline/aggregates_evaluation.h +++ b/Firestore/core/src/pipeline/aggregates_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_EVALUATION_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_EVALUATION_H_ +#ifndef FIRESTORE_CORE_SRC_PIPELINE_AGGREGATES_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_PIPELINE_AGGREGATES_EVALUATION_H_ #include #include "Firestore/core/src/pipeline/expression_evaluation.h" @@ -54,4 +54,4 @@ class CoreMinimum : public EvaluableExpr { } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_AGGREGATES_EVALUATION_H_ +#endif // FIRESTORE_CORE_SRC_PIPELINE_AGGREGATES_EVALUATION_H_ diff --git a/Firestore/core/src/pipeline/arithmetic_evaluation.h b/Firestore/core/src/pipeline/arithmetic_evaluation.h index 03cd2960295..4b7041a83f1 100644 --- a/Firestore/core/src/pipeline/arithmetic_evaluation.h +++ b/Firestore/core/src/pipeline/arithmetic_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARITHMETIC_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARITHMETIC_H_ +#ifndef FIRESTORE_CORE_SRC_PIPELINE_ARITHMETIC_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_PIPELINE_ARITHMETIC_EVALUATION_H_ #include #include "Firestore/core/src/pipeline/expression_evaluation.h" @@ -118,4 +118,4 @@ class CoreMod : public ArithmeticBase { } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARITHMETIC_H_ +#endif // FIRESTORE_CORE_SRC_PIPELINE_ARITHMETIC_EVALUATION_H_ diff --git a/Firestore/core/src/pipeline/array_evaluation.h b/Firestore/core/src/pipeline/array_evaluation.h index d8d64aff123..5de10eb81f7 100644 --- a/Firestore/core/src/pipeline/array_evaluation.h +++ b/Firestore/core/src/pipeline/array_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARRAY_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARRAY_H_ +#ifndef FIRESTORE_CORE_SRC_PIPELINE_ARRAY_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_PIPELINE_ARRAY_EVALUATION_H_ #include #include "Firestore/core/src/pipeline/expression_evaluation.h" @@ -93,4 +93,4 @@ class CoreArrayLength : public EvaluableExpr { } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_ARRAY_H_ +#endif // FIRESTORE_CORE_SRC_PIPELINE_ARRAY_EVALUATION_H_ diff --git a/Firestore/core/src/pipeline/comparison_evaluation.h b/Firestore/core/src/pipeline/comparison_evaluation.h index ccf517d9de6..0770df87d1e 100644 --- a/Firestore/core/src/pipeline/comparison_evaluation.h +++ b/Firestore/core/src/pipeline/comparison_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_COMPARISON_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_COMPARISON_H_ +#ifndef FIRESTORE_CORE_SRC_PIPELINE_COMPARISON_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_PIPELINE_COMPARISON_EVALUATION_H_ #include #include "Firestore/core/src/pipeline/expression_evaluation.h" @@ -113,4 +113,4 @@ class CoreGreaterThanOrEqual : public ComparisonBase { } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_COMPARISON_H_ +#endif // FIRESTORE_CORE_SRC_PIPELINE_COMPARISON_EVALUATION_H_ diff --git a/Firestore/core/src/pipeline/expression_evaluation.h b/Firestore/core/src/pipeline/expression_evaluation.h index fa44060c3bb..c8b341e27f3 100644 --- a/Firestore/core/src/pipeline/expression_evaluation.h +++ b/Firestore/core/src/pipeline/expression_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_EVALUATION_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_EVALUATION_H_ +#ifndef FIRESTORE_CORE_SRC_PIPELINE_EXPRESSION_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_PIPELINE_EXPRESSION_EVALUATION_H_ #include #include @@ -152,4 +152,4 @@ std::unique_ptr FunctionToEvaluable( } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EXPRESSION_EVALUATION_H_ +#endif // FIRESTORE_CORE_SRC_PIPELINE_EXPRESSION_EVALUATION_H_ diff --git a/Firestore/core/src/pipeline/logical_evaluation.h b/Firestore/core/src/pipeline/logical_evaluation.h index 2fb39d9b11a..8ae7e53bb9d 100644 --- a/Firestore/core/src/pipeline/logical_evaluation.h +++ b/Firestore/core/src/pipeline/logical_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_LOGICAL_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_LOGICAL_H_ +#ifndef FIRESTORE_CORE_SRC_PIPELINE_LOGICAL_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_PIPELINE_LOGICAL_EVALUATION_H_ #include #include "Firestore/core/src/pipeline/expression_evaluation.h" @@ -119,4 +119,4 @@ class CoreNot : public EvaluableExpr { } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_LOGICAL_H_ +#endif // FIRESTORE_CORE_SRC_PIPELINE_LOGICAL_EVALUATION_H_ diff --git a/Firestore/core/src/pipeline/map_evaluation.h b/Firestore/core/src/pipeline/map_evaluation.h index f4ea4b18614..5b6adaa80bd 100644 --- a/Firestore/core/src/pipeline/map_evaluation.h +++ b/Firestore/core/src/pipeline/map_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_MAP_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_MAP_H_ +#ifndef FIRESTORE_CORE_SRC_PIPELINE_MAP_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_PIPELINE_MAP_EVALUATION_H_ #include #include "Firestore/core/src/pipeline/expression_evaluation.h" @@ -41,4 +41,4 @@ class CoreMapGet : public EvaluableExpr { } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_MAP_H_ +#endif // FIRESTORE_CORE_SRC_PIPELINE_MAP_EVALUATION_H_ diff --git a/Firestore/core/src/pipeline/string_evaluation.h b/Firestore/core/src/pipeline/string_evaluation.h index 181b986d0e5..5e0028ac10d 100644 --- a/Firestore/core/src/pipeline/string_evaluation.h +++ b/Firestore/core/src/pipeline/string_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_STRING_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_STRING_H_ +#ifndef FIRESTORE_CORE_SRC_PIPELINE_STRING_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_PIPELINE_STRING_EVALUATION_H_ #include #include @@ -208,4 +208,4 @@ class CoreLike : public StringSearchBase { } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_STRING_H_ +#endif // FIRESTORE_CORE_SRC_PIPELINE_STRING_EVALUATION_H_ diff --git a/Firestore/core/src/pipeline/timestamp_evaluation.h b/Firestore/core/src/pipeline/timestamp_evaluation.h index 5b5dc9a2321..3e2cb53b9f5 100644 --- a/Firestore/core/src/pipeline/timestamp_evaluation.h +++ b/Firestore/core/src/pipeline/timestamp_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TIMESTAMP_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TIMESTAMP_H_ +#ifndef FIRESTORE_CORE_SRC_PIPELINE_TIMESTAMP_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_PIPELINE_TIMESTAMP_EVALUATION_H_ #include #include "Firestore/core/src/pipeline/expression_evaluation.h" @@ -154,4 +154,4 @@ class CoreTimestampSub : public TimestampArithmeticBase { } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TIMESTAMP_H_ +#endif // FIRESTORE_CORE_SRC_PIPELINE_TIMESTAMP_EVALUATION_H_ diff --git a/Firestore/core/src/pipeline/type_evaluation.h b/Firestore/core/src/pipeline/type_evaluation.h index 86d431dd1d6..1a05f9f330f 100644 --- a/Firestore/core/src/pipeline/type_evaluation.h +++ b/Firestore/core/src/pipeline/type_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TYPE_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TYPE_H_ +#ifndef FIRESTORE_CORE_SRC_PIPELINE_TYPE_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_PIPELINE_TYPE_EVALUATION_H_ #include #include "Firestore/core/src/pipeline/expression_evaluation.h" @@ -106,4 +106,4 @@ class CoreExists : public EvaluableExpr { } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_TYPE_H_ +#endif // FIRESTORE_CORE_SRC_PIPELINE_TYPE_EVALUATION_H_ diff --git a/Firestore/core/src/pipeline/util_evaluation.h b/Firestore/core/src/pipeline/util_evaluation.h index bb2cd6cdeb7..f04a5077e44 100644 --- a/Firestore/core/src/pipeline/util_evaluation.h +++ b/Firestore/core/src/pipeline/util_evaluation.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_UTIL_H_ -#define FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_UTIL_H_ +#ifndef FIRESTORE_CORE_SRC_PIPELINE_UTIL_EVALUATION_H_ +#define FIRESTORE_CORE_SRC_PIPELINE_UTIL_EVALUATION_H_ #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" #include "Firestore/core/src/nanopb/message.h" @@ -37,4 +37,4 @@ absl::optional SafeMod(int64_t lhs, int64_t rhs); } // namespace firestore } // namespace firebase -#endif // FIRESTORE_CORE_SRC_CORE_PIPELINE_EVALUATION_UTIL_H_ +#endif // FIRESTORE_CORE_SRC_PIPELINE_UTIL_EVALUATION_H_