예제 #1
0
 public void Delete(SerializableTest wrapper)
 {
     DeleteTest test = wrapper.Test.Delete;
     Check(test.IsError, test.Request, batch =>
     {
         DocumentReference doc = GetDocumentReference(test.DocRefPath);
         var precondition = Precondition.FromProto(test.Precondition);
         batch.Delete(doc, precondition);
     });
 }
예제 #2
0
 public void Create(SerializableTest wrapper)
 {
     CreateTest test = wrapper.Test.Create;
     Check(test.IsError, test.Request, batch =>
     {
         DocumentReference doc = GetDocumentReference(test.DocRefPath);
         object documentData = DeserializeJson(test.JsonData);
         batch.Create(doc, documentData);
     });
 }
예제 #3
0
 public void Update(SerializableTest wrapper)
 {
     UpdateTest test = wrapper.Test.Update;
     Check(test.IsError, test.Request, batch =>
     {
         DocumentReference doc = GetDocumentReference(test.DocRefPath);
         var documentData = (Dictionary<string, object>) DeserializeJson(test.JsonData);
         var precondition = Precondition.FromProto(test.Precondition);
         var updates = documentData.ToDictionary(pair => Firestore.FieldPath.FromDotSeparatedString(pair.Key), pair => pair.Value);
         batch.Update(doc, updates, precondition);
     });
 }
예제 #4
0
 public void Set(SerializableTest wrapper)
 {
     SetTest test = wrapper.Test.Set;
     Check(test.IsError, test.Request, batch =>
     {
         DocumentReference doc = GetDocumentReference(test.DocRefPath);
         object documentData = DeserializeJson(test.JsonData);
         var setOptions = test.Option == null ? null :
             test.Option.All ? SetOptions.MergeAll :
             SetOptions.MergeFields(test.Option.Fields.Select(ConvertFieldPath).ToArray());
         batch.Set(doc, documentData, setOptions);
     });
 }
예제 #5
0
 public void UpdatePaths(SerializableTest wrapper)
 {
     UpdatePathsTest test = wrapper.Test.UpdatePaths;
     Check(test.IsError, test.Request, batch =>
     {
         DocumentReference doc = GetDocumentReference(test.DocRefPath);
         Dictionary<Firestore.FieldPath, object> updates = test.FieldPaths
             .Zip(test.JsonValues, (path, value) => (path, value))
             .ToDictionary(tuple => ConvertFieldPath(tuple.path), tuple => (object) DeserializeJson(tuple.value));
         var precondition = Precondition.FromProto(test.Precondition);
         batch.Update(doc, updates, precondition);
     });
 }
예제 #6
0
        public void Query(SerializableTest wrapper)
        {
            QueryTest test = wrapper.Test.Query;

            if (test.IsError)
            {
                var exception = Assert.ThrowsAny <Exception>(() => BuildQuery());
                Assert.True(exception is ArgumentException || exception is InvalidOperationException, $"Exception type: {exception.GetType()}");
            }
            else
            {
                var query = BuildQuery();
                Assert.Equal(test.Query, query.ToStructuredQuery());
            }

            Query BuildQuery()
            {
                Query query = GetCollectionReference(test.CollPath);

                foreach (var clause in test.Clauses)
                {
                    switch (clause.ClauseCase)
                    {
                    case Clause.ClauseOneofCase.EndAt:
                        query = query.EndAt(ConvertCursor(clause.EndAt));
                        break;

                    case Clause.ClauseOneofCase.EndBefore:
                        query = query.EndBefore(ConvertCursor(clause.EndBefore));
                        break;

                    case Clause.ClauseOneofCase.Limit:
                        query = query.Limit(clause.Limit);
                        break;

                    case Clause.ClauseOneofCase.Offset:
                        query = query.Offset(clause.Offset);
                        break;

                    case Clause.ClauseOneofCase.OrderBy:
                        var ordering = clause.OrderBy;
                        var path     = ConvertFieldPath(ordering.Path);
                        query = ordering.Direction == "asc" ? query.OrderBy(path) : query.OrderByDescending(path);
                        break;

                    case Clause.ClauseOneofCase.Select:
                        query = query.Select(clause.Select.Fields.Select(ConvertFieldPath).ToArray());
                        break;

                    case Clause.ClauseOneofCase.StartAfter:
                        query = query.StartAfter(ConvertCursor(clause.StartAfter));
                        break;

                    case Clause.ClauseOneofCase.StartAt:
                        query = query.StartAt(ConvertCursor(clause.StartAt));
                        break;

                    case Clause.ClauseOneofCase.Where:
                        var filterPath = ConvertFieldPath(clause.Where.Path);
                        if (!QueryOperators.TryGetValue(clause.Where.Op, out var filterProvider))
                        {
                            throw new ArgumentException($"Invalid where operator: {clause.Where.Op}");
                        }
                        var value = DeserializeJson(clause.Where.JsonValue);
                        query = filterProvider(query, filterPath, value);
                        break;

                    default:
                        throw new InvalidOperationException($"Unexpected clause case: {clause.ClauseCase}");
                    }
                }
                return(query);
            }

            // Note: dynamic to allow a DocumentSnapshot to be returned and used in overload resolution.
            dynamic ConvertCursor(Cursor cursor)
            {
                var docSnapshot = cursor.DocSnapshot;

                if (docSnapshot == null)
                {
                    return(cursor.JsonValues.Select(DeserializeJson).ToArray());
                }
                var docRef = GetDocumentReference(docSnapshot.Path);

                return(DocumentSnapshot.ForDocument(
                           docRef.Database,
                           new Document
                {
                    Name = docRef.Path,
                    Fields = { ValueSerializer.SerializeMap(DeserializeJson(cursor.DocSnapshot.JsonData)) },
                    CreateTime = wkt::Timestamp.FromDateTimeOffset(DateTimeOffset.MinValue),
                    UpdateTime = wkt::Timestamp.FromDateTimeOffset(DateTimeOffset.MinValue),
                },
                           Timestamp.FromDateTimeOffset(DateTimeOffset.MinValue)));
            }
        }
예제 #7
0
        public async Task Listen(SerializableTest wrapper)
        {
            ListenTest test  = wrapper.Test.Listen;
            var        db    = FirestoreDb.Create(ProjectId, DatabaseId, new FakeFirestoreClient());
            var        query = db.Collection("C").OrderBy("a");

            Func <Task> action = async() =>
            {
                List <QuerySnapshot> snapshots = new List <QuerySnapshot>();
                var watchState = new WatchState(query, (snapshot, token) => { snapshots.Add(snapshot); return(Task.FromResult(1)); });
                watchState.OnStreamInitialization(StreamInitializationCause.WatchStarting);
                foreach (var response in test.Responses)
                {
                    // Fix up the test response to use our watch target ID.
                    ReplaceWatchTargetId(response.TargetChange?.TargetIds);
                    ReplaceWatchTargetId(response.DocumentChange?.TargetIds);
                    ReplaceWatchTargetId(response.DocumentChange?.RemovedTargetIds);
                    ReplaceWatchTargetId(response.DocumentDelete?.RemovedTargetIds);
                    ReplaceWatchTargetId(response.DocumentRemove?.RemovedTargetIds);

                    var result = await watchState.HandleResponseAsync(response, default);

                    if (result == WatchResponseResult.ResetStream)
                    {
                        watchState.OnStreamInitialization(StreamInitializationCause.ResetRequested);
                    }
                }
                var expectedSnapshots = test.Snapshots.Select(snapshot => ConvertSnapshot(snapshot)).ToList();
                Assert.Equal(expectedSnapshots, snapshots);
            };

            if (test.IsError)
            {
                // TODO: Should we actually check that it's only the last response that causes the exception?
                var exception = await Assert.ThrowsAnyAsync <Exception>(action);

                Assert.True(exception is ArgumentException || exception is InvalidOperationException,
                            $"Exception type: {exception.GetType()}");
            }
            else
            {
                await action();
            }

            // Different clients use different watch target IDs. The test data always uses 1
            // to mean "the target ID that the client uses".
            void ReplaceWatchTargetId(RepeatedField <int> ids)
            {
                if (ids == null)
                {
                    return;
                }
                for (int i = 0; i < ids.Count; i++)
                {
                    if (ids[i] == 1)
                    {
                        ids[i] = WatchStream.WatchTargetId;
                    }
                }
            }

            // Converts from a test proto snapshot to a QuerySnapshot
            QuerySnapshot ConvertSnapshot(Snapshot snapshot)
            {
                var readTime = Timestamp.FromProto(snapshot.ReadTime);
                var changes  = snapshot.Changes.Select(change => ConvertChange(change, readTime)).ToList();
                var docs     = snapshot.Docs.Select(doc => DocumentSnapshot.ForDocument(db, doc, readTime)).ToList();

                return(QuerySnapshot.ForChanges(query, docs, changes, readTime));
            }

            DocumentChange ConvertChange(DocChange change, Timestamp readTime)
            {
                var snapshot = DocumentSnapshot.ForDocument(db, change.Doc, readTime);

                return(new DocumentChange(snapshot, (DocumentChange.Type)change.Kind,
                                          change.OldIndex == -1 ? default(int?) : change.OldIndex, change.NewIndex == -1 ? default(int?) : change.NewIndex));
            }
        }