From fdc4c4ee78731add1a8f4dd4bb7623fcce9b32cd Mon Sep 17 00:00:00 2001 From: Morgan Chen Date: Tue, 11 Nov 2025 09:04:14 -0800 Subject: [PATCH 01/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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 b34463a3a774a248d44e9f8705e4ec3317b181ba Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 26 Nov 2025 13:48:36 -0500 Subject: [PATCH 27/33] add Expression.asBoolean --- .../xcschemes/Firestore_Example_iOS.xcscheme | 12 ++ .../Source/ExpressionImplementation.swift | 99 +++++---- .../Pipeline/Expressions/Expression.swift | 5 + .../BooleanExpression.swift | 201 +++++------------- .../Tests/Integration/PipelineApiTests.swift | 3 - .../Tests/Integration/PipelineTests.swift | 9 +- 6 files changed, 133 insertions(+), 196 deletions(-) diff --git a/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Example_iOS.xcscheme b/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Example_iOS.xcscheme index 1df610c09a8..279780fe448 100644 --- a/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Example_iOS.xcscheme +++ b/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Example_iOS.xcscheme @@ -89,6 +89,18 @@ ReferencedContainer = "container:Firestore.xcodeproj"> + + + + + + BooleanExpression { + if let boolExpr = self as? BooleanExpression { + return boolExpr + } + if let constant = self as? Constant { + return BooleanConstant(constant) + } + if let field = self as? Field { + return BooleanField(field) + } + if let funcExpr = self as? FunctionExpression { + return BooleanFunctionExpression(funcExpr) + } + // This should be unreachable if all expression types are handled. + fatalError("Unknown expression type \(Swift.type(of: self)) cannot be converted to BooleanExpression") + } + func `as`(_ name: String) -> AliasedExpression { return AliasedExpression(self, name) } @@ -474,38 +491,38 @@ public extension Expression { } func arrayContains(_ element: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "array_contains", args: [self, element]) + return BooleanFunctionExpression(functionName: "array_contains", args: [self, element]) } func arrayContains(_ element: Sendable) -> BooleanExpression { - return BooleanExpression( + return BooleanFunctionExpression( functionName: "array_contains", args: [self, Helper.sendableToExpr(element)] ) } func arrayContainsAll(_ values: [Expression]) -> BooleanExpression { - return BooleanExpression(functionName: "array_contains_all", args: [self, Helper.array(values)]) + return BooleanFunctionExpression(functionName: "array_contains_all", args: [self, Helper.array(values)]) } func arrayContainsAll(_ values: [Sendable]) -> BooleanExpression { - return BooleanExpression(functionName: "array_contains_all", args: [self, Helper.array(values)]) + return BooleanFunctionExpression(functionName: "array_contains_all", args: [self, Helper.array(values)]) } func arrayContainsAll(_ arrayExpression: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "array_contains_all", args: [self, arrayExpression]) + return BooleanFunctionExpression(functionName: "array_contains_all", args: [self, arrayExpression]) } func arrayContainsAny(_ values: [Expression]) -> BooleanExpression { - return BooleanExpression(functionName: "array_contains_any", args: [self, Helper.array(values)]) + return BooleanFunctionExpression(functionName: "array_contains_any", args: [self, Helper.array(values)]) } func arrayContainsAny(_ values: [Sendable]) -> BooleanExpression { - return BooleanExpression(functionName: "array_contains_any", args: [self, Helper.array(values)]) + return BooleanFunctionExpression(functionName: "array_contains_any", args: [self, Helper.array(values)]) } func arrayContainsAny(_ arrayExpression: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "array_contains_any", args: [self, arrayExpression]) + return BooleanFunctionExpression(functionName: "array_contains_any", args: [self, arrayExpression]) } func arrayLength() -> FunctionExpression { @@ -532,80 +549,80 @@ public extension Expression { } func greaterThan(_ other: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "greater_than", args: [self, other]) + return BooleanFunctionExpression(functionName: "greater_than", args: [self, other]) } func greaterThan(_ other: Sendable) -> BooleanExpression { let exprOther = Helper.sendableToExpr(other) - return BooleanExpression(functionName: "greater_than", args: [self, exprOther]) + return BooleanFunctionExpression(functionName: "greater_than", args: [self, exprOther]) } func greaterThanOrEqual(_ other: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "greater_than_or_equal", args: [self, other]) + return BooleanFunctionExpression(functionName: "greater_than_or_equal", args: [self, other]) } func greaterThanOrEqual(_ other: Sendable) -> BooleanExpression { let exprOther = Helper.sendableToExpr(other) - return BooleanExpression(functionName: "greater_than_or_equal", args: [self, exprOther]) + return BooleanFunctionExpression(functionName: "greater_than_or_equal", args: [self, exprOther]) } func lessThan(_ other: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "less_than", args: [self, other]) + return BooleanFunctionExpression(functionName: "less_than", args: [self, other]) } func lessThan(_ other: Sendable) -> BooleanExpression { let exprOther = Helper.sendableToExpr(other) - return BooleanExpression(functionName: "less_than", args: [self, exprOther]) + return BooleanFunctionExpression(functionName: "less_than", args: [self, exprOther]) } func lessThanOrEqual(_ other: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "less_than_or_equal", args: [self, other]) + return BooleanFunctionExpression(functionName: "less_than_or_equal", args: [self, other]) } func lessThanOrEqual(_ other: Sendable) -> BooleanExpression { let exprOther = Helper.sendableToExpr(other) - return BooleanExpression(functionName: "less_than_or_equal", args: [self, exprOther]) + return BooleanFunctionExpression(functionName: "less_than_or_equal", args: [self, exprOther]) } func equal(_ other: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "equal", args: [self, other]) + return BooleanFunctionExpression(functionName: "equal", args: [self, other]) } func equal(_ other: Sendable) -> BooleanExpression { let exprOther = Helper.sendableToExpr(other) - return BooleanExpression(functionName: "equal", args: [self, exprOther]) + return BooleanFunctionExpression(functionName: "equal", args: [self, exprOther]) } func notEqual(_ other: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "not_equal", args: [self, other]) + return BooleanFunctionExpression(functionName: "not_equal", args: [self, other]) } func notEqual(_ other: Sendable) -> BooleanExpression { - return BooleanExpression(functionName: "not_equal", args: [self, Helper.sendableToExpr(other)]) + return BooleanFunctionExpression(functionName: "not_equal", args: [self, Helper.sendableToExpr(other)]) } func equalAny(_ others: [Expression]) -> BooleanExpression { - return BooleanExpression(functionName: "equal_any", args: [self, Helper.array(others)]) + return BooleanFunctionExpression(functionName: "equal_any", args: [self, Helper.array(others)]) } func equalAny(_ others: [Sendable]) -> BooleanExpression { - return BooleanExpression(functionName: "equal_any", args: [self, Helper.array(others)]) + return BooleanFunctionExpression(functionName: "equal_any", args: [self, Helper.array(others)]) } func equalAny(_ arrayExpression: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "equal_any", args: [self, arrayExpression]) + return BooleanFunctionExpression(functionName: "equal_any", args: [self, arrayExpression]) } func notEqualAny(_ others: [Expression]) -> BooleanExpression { - return BooleanExpression(functionName: "not_equal_any", args: [self, Helper.array(others)]) + return BooleanFunctionExpression(functionName: "not_equal_any", args: [self, Helper.array(others)]) } func notEqualAny(_ others: [Sendable]) -> BooleanExpression { - return BooleanExpression(functionName: "not_equal_any", args: [self, Helper.array(others)]) + return BooleanFunctionExpression(functionName: "not_equal_any", args: [self, Helper.array(others)]) } func notEqualAny(_ arrayExpression: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "not_equal_any", args: [self, arrayExpression]) + return BooleanFunctionExpression(functionName: "not_equal_any", args: [self, arrayExpression]) } // MARK: Checks @@ -613,15 +630,15 @@ public extension Expression { // --- Added Type Check Operations --- func exists() -> BooleanExpression { - return BooleanExpression(functionName: "exists", args: [self]) + return BooleanFunctionExpression(functionName: "exists", args: [self]) } func isError() -> BooleanExpression { - return BooleanExpression(functionName: "is_error", args: [self]) + return BooleanFunctionExpression(functionName: "is_error", args: [self]) } func isAbsent() -> BooleanExpression { - return BooleanExpression(functionName: "is_absent", args: [self]) + return BooleanFunctionExpression(functionName: "is_absent", args: [self]) } // --- Added String Operations --- @@ -647,63 +664,63 @@ public extension Expression { } func like(_ pattern: String) -> BooleanExpression { - return BooleanExpression(functionName: "like", args: [self, Helper.sendableToExpr(pattern)]) + return BooleanFunctionExpression(functionName: "like", args: [self, Helper.sendableToExpr(pattern)]) } func like(_ pattern: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "like", args: [self, pattern]) + return BooleanFunctionExpression(functionName: "like", args: [self, pattern]) } func regexContains(_ pattern: String) -> BooleanExpression { - return BooleanExpression( + return BooleanFunctionExpression( functionName: "regex_contains", args: [self, Helper.sendableToExpr(pattern)] ) } func regexContains(_ pattern: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "regex_contains", args: [self, pattern]) + return BooleanFunctionExpression(functionName: "regex_contains", args: [self, pattern]) } func regexMatch(_ pattern: String) -> BooleanExpression { - return BooleanExpression( + return BooleanFunctionExpression( functionName: "regex_match", args: [self, Helper.sendableToExpr(pattern)] ) } func regexMatch(_ pattern: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "regex_match", args: [self, pattern]) + return BooleanFunctionExpression(functionName: "regex_match", args: [self, pattern]) } func stringContains(_ substring: String) -> BooleanExpression { - return BooleanExpression( + return BooleanFunctionExpression( functionName: "string_contains", args: [self, Helper.sendableToExpr(substring)] ) } func stringContains(_ expression: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "string_contains", args: [self, expression]) + return BooleanFunctionExpression(functionName: "string_contains", args: [self, expression]) } func startsWith(_ prefix: String) -> BooleanExpression { - return BooleanExpression( + return BooleanFunctionExpression( functionName: "starts_with", args: [self, Helper.sendableToExpr(prefix)] ) } func startsWith(_ prefix: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "starts_with", args: [self, prefix]) + return BooleanFunctionExpression(functionName: "starts_with", args: [self, prefix]) } func endsWith(_ suffix: String) -> BooleanExpression { - return BooleanExpression(functionName: "ends_with", args: [self, Helper.sendableToExpr(suffix)]) + return BooleanFunctionExpression(functionName: "ends_with", args: [self, Helper.sendableToExpr(suffix)]) } func endsWith(_ suffix: Expression) -> BooleanExpression { - return BooleanExpression(functionName: "ends_with", args: [self, suffix]) + return BooleanFunctionExpression(functionName: "ends_with", args: [self, suffix]) } func toLower() -> FunctionExpression { diff --git a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/Expression.swift b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/Expression.swift index 8b3367b299c..fb2475f3140 100644 --- a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/Expression.swift +++ b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/Expression.swift @@ -20,6 +20,11 @@ import Foundation public protocol Expression: Sendable { + /// Casts the expression to a `BooleanExpression`. + /// + /// - Returns: A `BooleanExpression` representing the same expression. + func asBoolean() -> BooleanExpression + /// Assigns an alias to this expression. /// /// Aliases are useful for renaming fields in the output of a stage or for giving meaningful diff --git a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift index 700d4aa0476..80ebe316774 100644 --- a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift +++ b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift @@ -14,163 +14,68 @@ import Foundation -/// -/// A `BooleanExpression` is a specialized `FunctionExpression` that evaluates to a boolean value. -/// -/// It is used to construct conditional logic within Firestore pipelines, such as in `where` -/// clauses or `ConditionalExpression`. `BooleanExpression` instances can be combined using standard -/// logical operators (`&&`, `||`, `!`, `^`) to create complex conditions. -/// -/// Example usage in a `where` clause: -/// ```swift -/// firestore.pipeline() -/// .collection("products") -/// .where( -/// Field("price").greaterThan(100) && -/// (Field("category").equal("electronics") || Field("on_sale").equal(true)) -/// ) -/// ``` -public class BooleanExpression: FunctionExpression, @unchecked Sendable { - override public init(functionName: String, args: [Expression]) { - super.init(functionName: functionName, args: args) - } +public protocol BooleanExpression: Expression {} - /// Creates an aggregation that counts the number of documents for which this boolean expression - /// evaluates to `true`. - /// - /// This is useful for counting documents that meet a specific condition without retrieving the - /// documents themselves. - /// - /// ```swift - /// // Count how many books were published after 1980 - /// let post1980Condition = Field("published").greaterThan(1980) - /// firestore.pipeline() - /// .collection("books") - /// .aggregate([ - /// post1980Condition.countIf().as("modernBooksCount") - /// ]) - /// ``` - /// - /// - Returns: An `AggregateFunction` that performs the conditional count. - public func countIf() -> AggregateFunction { - return AggregateFunction(functionName: "count_if", args: [self]) +internal struct BooleanFunctionExpression: BooleanExpression, BridgeWrapper { + internal let expr: FunctionExpression + public var bridge: ExprBridge { return expr.bridge } + + internal init(_ expr: FunctionExpression) { + self.expr = expr } - /// Creates a conditional expression that returns one of two specified expressions based on the - /// result of this boolean expression. - /// - /// This is equivalent to a ternary operator (`condition ? then : else`). - /// - /// ```swift - /// // Create a new field "status" based on the "rating" field. - /// // If rating > 4.5, status is "top_rated", otherwise "regular". - /// firestore.pipeline() - /// .collection("products") - /// .addFields([ - /// Field("rating").greaterThan(4.5) - /// .then(Constant("top_rated"), else: Constant("regular")) - /// .as("status") - /// ]) - /// ``` - /// - /// - Parameters: - /// - thenExpression: The `Expression` to evaluate if this boolean expression is `true`. - /// - elseExpression: The `Expression` to evaluate if this boolean expression is `false`. - /// - Returns: A new `FunctionExpression` representing the conditional logic. - public func then(_ thenExpression: Expression, - else elseExpression: Expression) -> FunctionExpression { - return FunctionExpression( - functionName: "conditional", - args: [self, thenExpression, elseExpression] - ) + internal init(functionName: String, args: [Expression]) { + expr = FunctionExpression(functionName: functionName, args: args) } +} + +internal struct BooleanConstant: BooleanExpression, BridgeWrapper { + private let constant: Constant + public var bridge: ExprBridge { return constant.bridge } - /// Combines two boolean expressions with a logical AND (`&&`). - /// - /// The resulting expression is `true` only if both the left-hand side (`lhs`) and the right-hand - /// side (`rhs`) are `true`. - /// - /// ```swift - /// // Find books in the "Fantasy" genre with a rating greater than 4.5 - /// firestore.pipeline() - /// .collection("books") - /// .where( - /// Field("genre").equal("Fantasy") && Field("rating").greaterThan(4.5) - /// ) - /// ``` - /// - /// - Parameters: - /// - lhs: The left-hand boolean expression. - /// - rhs: The right-hand boolean expression. - /// - Returns: A new `BooleanExpression` representing the logical AND. - public static func && (lhs: BooleanExpression, - rhs: @autoclosure () throws -> BooleanExpression) rethrows - -> BooleanExpression { - try BooleanExpression(functionName: "and", args: [lhs, rhs()]) + internal init(_ constant: Constant) { + self.constant = constant } +} - /// Combines two boolean expressions with a logical OR (`||`). - /// - /// The resulting expression is `true` if either the left-hand side (`lhs`) or the right-hand - /// side (`rhs`) is `true`. - /// - /// ```swift - /// // Find books that are either in the "Romance" genre or were published before 1900 - /// firestore.pipeline() - /// .collection("books") - /// .where( - /// Field("genre").equal("Romance") || Field("published").lessThan(1900) - /// ) - /// ``` - /// - /// - Parameters: - /// - lhs: The left-hand boolean expression. - /// - rhs: The right-hand boolean expression. - /// - Returns: A new `BooleanExpression` representing the logical OR. - public static func || (lhs: BooleanExpression, - rhs: @autoclosure () throws -> BooleanExpression) rethrows - -> BooleanExpression { - try BooleanExpression(functionName: "or", args: [lhs, rhs()]) +internal struct BooleanField: BooleanExpression, BridgeWrapper { + private let field: Field + public var bridge: ExprBridge { return field.bridge } + + internal init(_ field: Field) { + self.field = field } +} + +public func && (lhs: BooleanExpression, + rhs: @autoclosure () throws -> BooleanExpression) rethrows -> BooleanExpression { + return try BooleanFunctionExpression(functionName: "and", args: [lhs, rhs()]) +} + +public func || (lhs: BooleanExpression, + rhs: @autoclosure () throws -> BooleanExpression) rethrows -> BooleanExpression { + return try BooleanFunctionExpression(functionName: "or", args: [lhs, rhs()]) +} + +public func ^ (lhs: BooleanExpression, + rhs: @autoclosure () throws -> BooleanExpression) rethrows -> BooleanExpression { + return try BooleanFunctionExpression(functionName: "xor", args: [lhs, rhs()]) +} + +public prefix func ! (lhs: BooleanExpression) -> BooleanExpression { + return BooleanFunctionExpression(functionName: "not", args: [lhs]) +} - /// Combines two boolean expressions with a logical XOR (`^`). - /// - /// The resulting expression is `true` if the left-hand side (`lhs`) and the right-hand side - /// (`rhs`) have different boolean values. - /// - /// ```swift - /// // Find books that are in the "Dystopian" genre OR have a rating of 5.0, but not both. - /// firestore.pipeline() - /// .collection("books") - /// .where( - /// Field("genre").equal("Dystopian") ^ Field("rating").equal(5.0) - /// ) - /// ``` - /// - /// - Parameters: - /// - lhs: The left-hand boolean expression. - /// - rhs: The right-hand boolean expression. - /// - Returns: A new `BooleanExpression` representing the logical XOR. - public static func ^ (lhs: BooleanExpression, - rhs: @autoclosure () throws -> BooleanExpression) rethrows - -> BooleanExpression { - try BooleanExpression(functionName: "xor", args: [lhs, rhs()]) +public extension BooleanExpression { + func countIf() -> AggregateFunction { + return AggregateFunction(functionName: "count_if", args: [self]) } - /// Negates a boolean expression with a logical NOT (`!`). - /// - /// The resulting expression is `true` if the original expression is `false`, and vice versa. - /// - /// ```swift - /// // Find books that are NOT in the "Science Fiction" genre - /// firestore.pipeline() - /// .collection("books") - /// .where(!Field("genre").equal("Science Fiction")) - /// ``` - /// - /// - Parameter lhs: The boolean expression to negate. - /// - Returns: A new `BooleanExpression` representing the logical NOT. - public static prefix func ! (lhs: BooleanExpression) -> BooleanExpression { - return BooleanExpression(functionName: "not", args: [lhs]) + func then(_ thenExpression: Expression, + else elseExpression: Expression) -> FunctionExpression { + return FunctionExpression( + functionName: "conditional", + args: [self, thenExpression, elseExpression] + ) } -} +} \ No newline at end of file diff --git a/Firestore/Swift/Tests/Integration/PipelineApiTests.swift b/Firestore/Swift/Tests/Integration/PipelineApiTests.swift index 20096529f97..e4434b97830 100644 --- a/Firestore/Swift/Tests/Integration/PipelineApiTests.swift +++ b/Firestore/Swift/Tests/Integration/PipelineApiTests.swift @@ -405,9 +405,6 @@ final class PipelineApiTests: FSTIntegrationTestCase { // This is the same of the logicalMin('price', 0)', if it did not exist _ = FunctionExpression(functionName: "logicalMin", args: [Field("price"), Constant(0)]) - // Create a generic BooleanExpr for use where BooleanExpr is required - _ = BooleanExpression(functionName: "eq", args: [Field("price"), Constant(10)]) - // Create a generic AggregateFunction for use where AggregateFunction is required _ = AggregateFunction(functionName: "sum", args: [Field("price")]) } diff --git a/Firestore/Swift/Tests/Integration/PipelineTests.swift b/Firestore/Swift/Tests/Integration/PipelineTests.swift index 9eb545cb617..2e5ba23c332 100644 --- a/Firestore/Swift/Tests/Integration/PipelineTests.swift +++ b/Firestore/Swift/Tests/Integration/PipelineTests.swift @@ -2783,9 +2783,10 @@ class PipelineIntegrationTests: FSTIntegrationTestCase { let pipeline = db.pipeline() .collection(collRef.path) .where( - BooleanExpression(functionName: "and", args: [Field("rating").greaterThan(0), + FunctionExpression(functionName: "and", args: [Field("rating").greaterThan(0), Field("title").charLength().lessThan(5), - Field("tags").arrayContains("propaganda")]) + Field("tags") + .arrayContains("propaganda")]).asBoolean() ) .select(["title"]) @@ -2806,10 +2807,10 @@ class PipelineIntegrationTests: FSTIntegrationTestCase { let pipeline = db.pipeline() .collection(collRef.path) - .where(BooleanExpression( + .where(FunctionExpression( functionName: "array_contains_any", args: [Field("tags"), ArrayExpression(["politics"])] - )) + ).asBoolean()) .select([Field("title")]) let snapshot = try await pipeline.execute() From dfe49762ea192ee2eb0a5d15af77475134532221 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 26 Nov 2025 15:47:03 -0500 Subject: [PATCH 28/33] add tests and format code --- .../Source/ExpressionImplementation.swift | 59 +++++++++++++++---- .../BooleanExpression.swift | 24 ++++---- .../Tests/Integration/PipelineTests.swift | 35 ++++++++++- 3 files changed, 92 insertions(+), 26 deletions(-) diff --git a/Firestore/Swift/Source/ExpressionImplementation.swift b/Firestore/Swift/Source/ExpressionImplementation.swift index aea684fb159..83dd834f11a 100644 --- a/Firestore/Swift/Source/ExpressionImplementation.swift +++ b/Firestore/Swift/Source/ExpressionImplementation.swift @@ -390,7 +390,9 @@ public extension Expression { return BooleanFunctionExpression(funcExpr) } // This should be unreachable if all expression types are handled. - fatalError("Unknown expression type \(Swift.type(of: self)) cannot be converted to BooleanExpression") + fatalError( + "Unknown expression type \(Swift.type(of: self)) cannot be converted to BooleanExpression" + ) } func `as`(_ name: String) -> AliasedExpression { @@ -502,27 +504,45 @@ public extension Expression { } func arrayContainsAll(_ values: [Expression]) -> BooleanExpression { - return BooleanFunctionExpression(functionName: "array_contains_all", args: [self, Helper.array(values)]) + return BooleanFunctionExpression( + functionName: "array_contains_all", + args: [self, Helper.array(values)] + ) } func arrayContainsAll(_ values: [Sendable]) -> BooleanExpression { - return BooleanFunctionExpression(functionName: "array_contains_all", args: [self, Helper.array(values)]) + return BooleanFunctionExpression( + functionName: "array_contains_all", + args: [self, Helper.array(values)] + ) } func arrayContainsAll(_ arrayExpression: Expression) -> BooleanExpression { - return BooleanFunctionExpression(functionName: "array_contains_all", args: [self, arrayExpression]) + return BooleanFunctionExpression( + functionName: "array_contains_all", + args: [self, arrayExpression] + ) } func arrayContainsAny(_ values: [Expression]) -> BooleanExpression { - return BooleanFunctionExpression(functionName: "array_contains_any", args: [self, Helper.array(values)]) + return BooleanFunctionExpression( + functionName: "array_contains_any", + args: [self, Helper.array(values)] + ) } func arrayContainsAny(_ values: [Sendable]) -> BooleanExpression { - return BooleanFunctionExpression(functionName: "array_contains_any", args: [self, Helper.array(values)]) + return BooleanFunctionExpression( + functionName: "array_contains_any", + args: [self, Helper.array(values)] + ) } func arrayContainsAny(_ arrayExpression: Expression) -> BooleanExpression { - return BooleanFunctionExpression(functionName: "array_contains_any", args: [self, arrayExpression]) + return BooleanFunctionExpression( + functionName: "array_contains_any", + args: [self, arrayExpression] + ) } func arrayLength() -> FunctionExpression { @@ -598,7 +618,10 @@ public extension Expression { } func notEqual(_ other: Sendable) -> BooleanExpression { - return BooleanFunctionExpression(functionName: "not_equal", args: [self, Helper.sendableToExpr(other)]) + return BooleanFunctionExpression( + functionName: "not_equal", + args: [self, Helper.sendableToExpr(other)] + ) } func equalAny(_ others: [Expression]) -> BooleanExpression { @@ -614,11 +637,17 @@ public extension Expression { } func notEqualAny(_ others: [Expression]) -> BooleanExpression { - return BooleanFunctionExpression(functionName: "not_equal_any", args: [self, Helper.array(others)]) + return BooleanFunctionExpression( + functionName: "not_equal_any", + args: [self, Helper.array(others)] + ) } func notEqualAny(_ others: [Sendable]) -> BooleanExpression { - return BooleanFunctionExpression(functionName: "not_equal_any", args: [self, Helper.array(others)]) + return BooleanFunctionExpression( + functionName: "not_equal_any", + args: [self, Helper.array(others)] + ) } func notEqualAny(_ arrayExpression: Expression) -> BooleanExpression { @@ -664,7 +693,10 @@ public extension Expression { } func like(_ pattern: String) -> BooleanExpression { - return BooleanFunctionExpression(functionName: "like", args: [self, Helper.sendableToExpr(pattern)]) + return BooleanFunctionExpression( + functionName: "like", + args: [self, Helper.sendableToExpr(pattern)] + ) } func like(_ pattern: Expression) -> BooleanExpression { @@ -716,7 +748,10 @@ public extension Expression { } func endsWith(_ suffix: String) -> BooleanExpression { - return BooleanFunctionExpression(functionName: "ends_with", args: [self, Helper.sendableToExpr(suffix)]) + return BooleanFunctionExpression( + functionName: "ends_with", + args: [self, Helper.sendableToExpr(suffix)] + ) } func endsWith(_ suffix: Expression) -> BooleanExpression { diff --git a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift index 80ebe316774..d7d7c1f8e9d 100644 --- a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift +++ b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift @@ -16,49 +16,49 @@ import Foundation public protocol BooleanExpression: Expression {} -internal struct BooleanFunctionExpression: BooleanExpression, BridgeWrapper { - internal let expr: FunctionExpression +struct BooleanFunctionExpression: BooleanExpression, BridgeWrapper { + let expr: FunctionExpression public var bridge: ExprBridge { return expr.bridge } - internal init(_ expr: FunctionExpression) { + init(_ expr: FunctionExpression) { self.expr = expr } - internal init(functionName: String, args: [Expression]) { + init(functionName: String, args: [Expression]) { expr = FunctionExpression(functionName: functionName, args: args) } } -internal struct BooleanConstant: BooleanExpression, BridgeWrapper { +struct BooleanConstant: BooleanExpression, BridgeWrapper { private let constant: Constant public var bridge: ExprBridge { return constant.bridge } - internal init(_ constant: Constant) { + init(_ constant: Constant) { self.constant = constant } } -internal struct BooleanField: BooleanExpression, BridgeWrapper { +struct BooleanField: BooleanExpression, BridgeWrapper { private let field: Field public var bridge: ExprBridge { return field.bridge } - internal init(_ field: Field) { + init(_ field: Field) { self.field = field } } public func && (lhs: BooleanExpression, - rhs: @autoclosure () throws -> BooleanExpression) rethrows -> BooleanExpression { + rhs: @autoclosure () throws -> BooleanExpression) rethrows -> BooleanExpression { return try BooleanFunctionExpression(functionName: "and", args: [lhs, rhs()]) } public func || (lhs: BooleanExpression, - rhs: @autoclosure () throws -> BooleanExpression) rethrows -> BooleanExpression { + rhs: @autoclosure () throws -> BooleanExpression) rethrows -> BooleanExpression { return try BooleanFunctionExpression(functionName: "or", args: [lhs, rhs()]) } public func ^ (lhs: BooleanExpression, - rhs: @autoclosure () throws -> BooleanExpression) rethrows -> BooleanExpression { + rhs: @autoclosure () throws -> BooleanExpression) rethrows -> BooleanExpression { return try BooleanFunctionExpression(functionName: "xor", args: [lhs, rhs()]) } @@ -78,4 +78,4 @@ public extension BooleanExpression { args: [self, thenExpression, elseExpression] ) } -} \ No newline at end of file +} diff --git a/Firestore/Swift/Tests/Integration/PipelineTests.swift b/Firestore/Swift/Tests/Integration/PipelineTests.swift index 2e5ba23c332..050fd173068 100644 --- a/Firestore/Swift/Tests/Integration/PipelineTests.swift +++ b/Firestore/Swift/Tests/Integration/PipelineTests.swift @@ -2784,9 +2784,9 @@ class PipelineIntegrationTests: FSTIntegrationTestCase { .collection(collRef.path) .where( FunctionExpression(functionName: "and", args: [Field("rating").greaterThan(0), - Field("title").charLength().lessThan(5), + Field("title").charLength().lessThan(5), Field("tags") - .arrayContains("propaganda")]).asBoolean() + .arrayContains("propaganda")]).asBoolean() ) .select(["title"]) @@ -3910,4 +3910,35 @@ class PipelineIntegrationTests: FSTIntegrationTestCase { ] TestHelper.compare(snapshot: snapshot, expected: expectedResults, enforceOrder: true) } + + func testFieldAndConstantAsBooleanExpression() async throws { + let collRef = collectionRef(withDocuments: [ + "doc1": ["a": true], + "doc2": ["a": false], + "doc3": ["b": true], + ]) + let db = collRef.firestore + + var pipeline = db.pipeline() + .collection(collRef.path) + .where(Field("a").asBoolean()) + var snapshot = try await pipeline.execute() + TestHelper.compare(snapshot: snapshot, expectedIDs: ["doc1"], enforceOrder: false) + + pipeline = db.pipeline() + .collection(collRef.path) + .where(Constant(true).asBoolean()) + snapshot = try await pipeline.execute() + TestHelper.compare( + snapshot: snapshot, + expectedIDs: ["doc1", "doc2", "doc3"], + enforceOrder: false + ) + + pipeline = db.pipeline() + .collection(collRef.path) + .where(Constant(false).asBoolean()) + snapshot = try await pipeline.execute() + TestHelper.compare(snapshot: snapshot, expectedCount: 0) + } } From 9da9f0e30d72650969578aab273960f80aafd1d9 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 26 Nov 2025 16:25:14 -0500 Subject: [PATCH 29/33] add documentation --- .../xcschemes/Firestore_Example_iOS.xcscheme | 12 -- .../BooleanExpression.swift | 121 ++++++++++++++++++ 2 files changed, 121 insertions(+), 12 deletions(-) diff --git a/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Example_iOS.xcscheme b/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Example_iOS.xcscheme index 279780fe448..1df610c09a8 100644 --- a/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Example_iOS.xcscheme +++ b/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Example_iOS.xcscheme @@ -89,18 +89,6 @@ ReferencedContainer = "container:Firestore.xcodeproj"> - - - - - - BooleanExpression) rethrows -> BooleanExpression { return try BooleanFunctionExpression(functionName: "and", args: [lhs, rhs()]) } +/// Combines two boolean expressions with a logical OR (`||`). +/// +/// The resulting expression is `true` if either the left-hand side (`lhs`) or the right-hand +/// side (`rhs`) is `true`. +/// +/// ```swift +/// // Find books that are either in the "Romance" genre or were published before 1900 +/// firestore.pipeline() +/// .collection("books") +/// .where( +/// Field("genre").equal("Romance") || Field("published").lessThan(1900) +/// ) +/// ``` +/// +/// - Parameters: +/// - lhs: The left-hand boolean expression. +/// - rhs: The right-hand boolean expression. +/// - Returns: A new `BooleanExpression` representing the logical OR. public func || (lhs: BooleanExpression, rhs: @autoclosure () throws -> BooleanExpression) rethrows -> BooleanExpression { return try BooleanFunctionExpression(functionName: "or", args: [lhs, rhs()]) } +/// Combines two boolean expressions with a logical XOR (`^`). +/// +/// The resulting expression is `true` if the left-hand side (`lhs`) and the right-hand side +/// (`rhs`) have different boolean values. +/// +/// ```swift +/// // Find books that are in the "Dystopian" genre OR have a rating of 5.0, but not both. +/// firestore.pipeline() +/// .collection("books") +/// .where( +/// Field("genre").equal("Dystopian") ^ Field("rating").equal(5.0) +/// ) +/// ``` +/// +/// - Parameters: +/// - lhs: The left-hand boolean expression. +/// - rhs: The right-hand boolean expression. +/// - Returns: A new `BooleanExpression` representing the logical XOR. public func ^ (lhs: BooleanExpression, rhs: @autoclosure () throws -> BooleanExpression) rethrows -> BooleanExpression { return try BooleanFunctionExpression(functionName: "xor", args: [lhs, rhs()]) } +/// Negates a boolean expression with a logical NOT (`!`). +/// +/// The resulting expression is `true` if the original expression is `false`, and vice versa. +/// +/// ```swift +/// // Find books that are NOT in the "Science Fiction" genre +/// firestore.pipeline() +/// .collection("books") +/// .where(!Field("genre").equal("Science Fiction")) +/// ``` +/// +/// - Parameter lhs: The boolean expression to negate. +/// - Returns: A new `BooleanExpression` representing the logical NOT. public prefix func ! (lhs: BooleanExpression) -> BooleanExpression { return BooleanFunctionExpression(functionName: "not", args: [lhs]) } public extension BooleanExpression { + /// Creates an aggregation that counts the number of documents for which this boolean expression + /// evaluates to `true`. + /// + /// This is useful for counting documents that meet a specific condition without retrieving the + /// documents themselves. + /// + /// ```swift + /// // Count how many books were published after 1980 + /// let post1980Condition = Field("published").greaterThan(1980) + /// firestore.pipeline() + /// .collection("books") + /// .aggregate([ + /// post1980Condition.countIf().as("modernBooksCount") + /// ]) + /// ``` + /// + /// - Returns: An `AggregateFunction` that performs the conditional count. func countIf() -> AggregateFunction { return AggregateFunction(functionName: "count_if", args: [self]) } + /// Creates a conditional expression that returns one of two specified expressions based on the + /// result of this boolean expression. + /// + /// This is equivalent to a ternary operator (`condition ? then : else`). + /// + /// ```swift + /// // Create a new field "status" based on the "rating" field. + /// // If rating > 4.5, status is "top_rated", otherwise "regular". + /// firestore.pipeline() + /// .collection("products") + /// .addFields([ + /// Field("rating").greaterThan(4.5) + /// .then(Constant("top_rated"), else: Constant("regular")) + /// .as("status") + /// ]) + /// ``` + /// + /// - Parameters: + /// - thenExpression: The `Expression` to evaluate if this boolean expression is `true`. + /// - elseExpression: The `Expression` to evaluate if this boolean expression is `false`. + /// - Returns: A new `FunctionExpression` representing the conditional logic. func then(_ thenExpression: Expression, else elseExpression: Expression) -> FunctionExpression { return FunctionExpression( From 01d743007ab8f51306107333dd5c92e076620b7c Mon Sep 17 00:00:00 2001 From: cherylEnkidu <96084918+cherylEnkidu@users.noreply.github.com> Date: Wed, 26 Nov 2025 16:29:46 -0500 Subject: [PATCH 30/33] Update Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../Expressions/FunctionExpressions/BooleanExpression.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift index 85d436d0e91..a3dcb23e03e 100644 --- a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift +++ b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift @@ -167,7 +167,7 @@ public extension BooleanExpression { /// ``` /// /// - Returns: An `AggregateFunction` that performs the conditional count. - func countIf() -> AggregateFunction { + public func countIf() -> AggregateFunction { return AggregateFunction(functionName: "count_if", args: [self]) } From 233d9d60aeef7ad302653ef88306f376da0e47d3 Mon Sep 17 00:00:00 2001 From: cherylEnkidu <96084918+cherylEnkidu@users.noreply.github.com> Date: Wed, 26 Nov 2025 16:29:54 -0500 Subject: [PATCH 31/33] Update Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../Expressions/FunctionExpressions/BooleanExpression.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift index a3dcb23e03e..8e796eae2cc 100644 --- a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift +++ b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift @@ -192,7 +192,7 @@ public extension BooleanExpression { /// - thenExpression: The `Expression` to evaluate if this boolean expression is `true`. /// - elseExpression: The `Expression` to evaluate if this boolean expression is `false`. /// - Returns: A new `FunctionExpression` representing the conditional logic. - func then(_ thenExpression: Expression, + public func then(_ thenExpression: Expression, else elseExpression: Expression) -> FunctionExpression { return FunctionExpression( functionName: "conditional", From dfc9c5febff391c830cebc64c045ccc110b3b932 Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Wed, 26 Nov 2025 16:57:46 -0500 Subject: [PATCH 32/33] format --- .../Source/ExpressionImplementation.swift | 21 +++++++++---------- .../BooleanExpression.swift | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Firestore/Swift/Source/ExpressionImplementation.swift b/Firestore/Swift/Source/ExpressionImplementation.swift index 83dd834f11a..aecfb3c75b1 100644 --- a/Firestore/Swift/Source/ExpressionImplementation.swift +++ b/Firestore/Swift/Source/ExpressionImplementation.swift @@ -377,22 +377,21 @@ extension Expression { public extension Expression { func asBoolean() -> BooleanExpression { - if let boolExpr = self as? BooleanExpression { + switch self { + case let boolExpr as BooleanExpression: return boolExpr - } - if let constant = self as? Constant { + case let constant as Constant: return BooleanConstant(constant) - } - if let field = self as? Field { + case let field as Field: return BooleanField(field) - } - if let funcExpr = self as? FunctionExpression { + case let funcExpr as FunctionExpression: return BooleanFunctionExpression(funcExpr) + default: + // This should be unreachable if all expression types are handled. + fatalError( + "Unknown expression type \(Swift.type(of: self)) cannot be converted to BooleanExpression" + ) } - // This should be unreachable if all expression types are handled. - fatalError( - "Unknown expression type \(Swift.type(of: self)) cannot be converted to BooleanExpression" - ) } func `as`(_ name: String) -> AliasedExpression { diff --git a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift index 8e796eae2cc..85d436d0e91 100644 --- a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift +++ b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift @@ -167,7 +167,7 @@ public extension BooleanExpression { /// ``` /// /// - Returns: An `AggregateFunction` that performs the conditional count. - public func countIf() -> AggregateFunction { + func countIf() -> AggregateFunction { return AggregateFunction(functionName: "count_if", args: [self]) } @@ -192,7 +192,7 @@ public extension BooleanExpression { /// - thenExpression: The `Expression` to evaluate if this boolean expression is `true`. /// - elseExpression: The `Expression` to evaluate if this boolean expression is `false`. /// - Returns: A new `FunctionExpression` representing the conditional logic. - public func then(_ thenExpression: Expression, + func then(_ thenExpression: Expression, else elseExpression: Expression) -> FunctionExpression { return FunctionExpression( functionName: "conditional", From 1a267b1f8b65e7cfde57bc49e4ccce06c00cc84d Mon Sep 17 00:00:00 2001 From: cherylEnkidu Date: Fri, 28 Nov 2025 11:05:55 -0500 Subject: [PATCH 33/33] 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))