// Copyright 2019 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.
//

// Tests for firestore clients.

syntax = "proto3";

package google.cloud.conformance.firestore.v1;

option php_namespace = "Google\\Cloud\\Firestore\\Tests\\Conformance";
option csharp_namespace = "Google.Cloud.Firestore.Tests.Proto";
option java_outer_classname = "TestDefinition";
option java_package = "com.google.cloud.conformance.firestore.v1";

import "google/firestore/v1/common.proto";
import "google/firestore/v1/document.proto";
import "google/firestore/v1/firestore.proto";
import "google/firestore/v1/query.proto";
import "google/protobuf/timestamp.proto";

// A collection of tests.
message TestFile {
  repeated Test tests = 1;
}

// A Test describes a single client method call and its expected result.
message Test {
  string description = 1; // short description of the test
  string comment = 10; // a comment describing the behavior being tested

  oneof test {
    GetTest         get = 2;
    CreateTest      create = 3;
    SetTest         set = 4;
    UpdateTest      update = 5;
    UpdatePathsTest update_paths = 6;
    DeleteTest      delete = 7;
    QueryTest       query = 8;
    ListenTest      listen = 9;
  }
}

// Call to the DocumentRef.Get method.
message GetTest {
  // The path of the doc, e.g. "projects/projectID/databases/(default)/documents/C/d"
  string doc_ref_path = 1;

  // The request that the call should send to the Firestore service.
  google.firestore.v1.GetDocumentRequest request = 2;
}

// Call to DocumentRef.Create.
message CreateTest {
  // The path of the doc, e.g. "projects/projectID/databases/(default)/documents/C/d"
  string doc_ref_path = 1;

  // The data passed to Create, as JSON. The strings "Delete" and "ServerTimestamp"
  // denote the two special sentinel values. Values that could be interpreted as integers
  // (i.e. digit strings) should be treated as integers.
  string json_data = 2;

  // The request that the call should generate.
  google.firestore.v1.CommitRequest request = 3;

  // If true, the call should result in an error without generating a request.
  // If this is true, request should not be set.
  bool is_error = 4;
}

// A call to DocumentRef.Set.
message SetTest {
  string doc_ref_path = 1;         // path of doc
  SetOption option = 2;            // option to the Set call, if any
  string json_data = 3;            // data (see CreateTest.json_data)
  google.firestore.v1.CommitRequest request = 4; // expected request
  bool is_error = 5;               // call signals an error
}

// A call to the form of DocumentRef.Update that represents the data as a map
// or dictionary.
message UpdateTest {
  string doc_ref_path = 1; // path of doc
  google.firestore.v1.Precondition precondition = 2; // precondition in call, if any
  string json_data  = 3;   // data (see CreateTest.json_data)
  google.firestore.v1.CommitRequest request = 4; // expected request
  bool is_error = 5;       // call signals an error
}

// A call to the form of DocumentRef.Update that represents the data as a list
// of field paths and their values.
message UpdatePathsTest {
  string doc_ref_path = 1; // path of doc
  google.firestore.v1.Precondition precondition = 2; // precondition in call, if any
  // parallel sequences: field_paths[i] corresponds to json_values[i]
  repeated FieldPath field_paths = 3; // the argument field paths
  repeated string json_values = 4;    // the argument values, as JSON
  google.firestore.v1.CommitRequest request = 5; // expected rquest
  bool is_error = 6; // call signals an error
}

// A call to DocmentRef.Delete
message DeleteTest {
  string doc_ref_path = 1; // path of doc
  google.firestore.v1.Precondition precondition = 2;
  google.firestore.v1.CommitRequest request = 3; // expected rquest
  bool is_error = 4;       // call signals an error
}

// An option to the DocumentRef.Set call.
message SetOption {
  bool all = 1;                  // if true, merge all fields ("fields" is ignored).
  repeated FieldPath fields = 2; // field paths for a Merge option
}

message QueryTest {
  string coll_path = 1; // path of collection, e.g. "projects/projectID/databases/(default)/documents/C"
  repeated Clause clauses = 2;
  google.firestore.v1.StructuredQuery query = 3;
  bool is_error = 4;
}

message Clause {
  oneof clause {
    Select select = 1;
    Where where = 2;
    OrderBy order_by = 3;
    int32 offset = 4;
    int32 limit = 5;
    Cursor start_at = 6;
    Cursor start_after = 7;
    Cursor end_at = 8;
    Cursor end_before = 9;
  }
}

message Select {
  repeated FieldPath fields = 1;
}

message Where {
  FieldPath path = 1;
  string op = 2;
  string json_value = 3;
}

message OrderBy {
  FieldPath path = 1;
  string direction = 2; // "asc" or "desc"
}

message Cursor {
  // one of:
  DocSnapshot doc_snapshot = 1;
  repeated string json_values = 2;
}

message DocSnapshot {
  string path = 1;
  string json_data = 2;
}

message FieldPath {
  repeated string field = 1;
}

// A test of the Listen streaming RPC (a.k.a. FireStore watch).
// If the sequence of responses is provided to the implementation,
// it should produce the sequence of snapshots.
// If is_error is true, an error should occur after the snapshots.
//
// The tests assume that the query is
// Collection("projects/projectID/databases/(default)/documents/C").OrderBy("a", Ascending)
//
// The watch target ID used in these tests is 1. Test interpreters
// should either change their client's ID for testing,
// or change the ID in the tests before running them.
message ListenTest {
  repeated google.firestore.v1.ListenResponse responses = 1;
  repeated Snapshot snapshots = 2;
  bool is_error = 3;
}

message Snapshot {
  repeated google.firestore.v1.Document docs = 1;
  repeated DocChange changes = 2;
  google.protobuf.Timestamp read_time = 3;
}

message DocChange {
  enum Kind {
    KIND_UNSPECIFIED = 0;
    ADDED = 1;
    REMOVED = 2;
    MODIFIED = 3;
  }

  Kind kind = 1;
  google.firestore.v1.Document doc = 2;
  int32 old_index = 3;
  int32 new_index = 4;
}
