/*
* Copyright (C) 2019 The Android Open Source Project
*
* 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.
*/

syntax = "proto3";

package luci.resultdb.v1;

import public "tools/tradefederation/core/proto/resultdb/common.proto";

option go_package = "go.chromium.org/luci/resultdb/proto/v1;resultpb";
option java_package = "com.android.resultdb.proto";
option java_multiple_files = true;

// Represents a function TestResult -> bool.
// Empty message matches all test results.
//
// Most clients would want to set expected_results to
// VARIANTS_WITH_UNEXPECTED_RESULTS.
message TestResultPredicate {
  // A test result must have a test id matching this regular expression
  // entirely, i.e. the expression is implicitly wrapped with ^ and $.
  string test_id_regexp = 1;

  // A test result must have a variant satisfying this predicate.
  VariantPredicate variant = 2;

  // Filters test results based on TestResult.expected field.
  enum Expectancy {
    // All test results satisfy this.
    // WARNING: using this significantly increases response size and latency.
    ALL = 0;

    // A test result must belong to a test variant that has one or more
    // unexpected results. It can be used to fetch both unexpected and flakily
    // expected results.
    //
    // Note that the predicate is defined at the test variant level.
    // For example, if a test variant expects a PASS and has results
    // [FAIL, FAIL, PASS], then all results satisfy the predicate because
    // the variant satisfies the predicate.
    VARIANTS_WITH_UNEXPECTED_RESULTS = 1;

    // Similar to VARIANTS_WITH_UNEXPECTED_RESULTS, but the test variant
    // must not have any expected results.
    VARIANTS_WITH_ONLY_UNEXPECTED_RESULTS = 2;
  }

  // A test result must match this predicate based on TestResult.expected field.
  // Most clients would want to override this field because the default
  // typically causes a large response size.
  Expectancy expectancy = 3;

  // If true, filter out exonerated test variants.
  // Mutually exclusive with Expectancy.ALL.
  //
  // If false, the filter is NOT applied.
  // That is, the test result may or may not be exonerated.
  bool exclude_exonerated = 4;
}

// Represents a function TestExoneration -> bool.
// Empty message matches all test exonerations.
message TestExonerationPredicate {
  // A test exoneration must have a test id matching this regular expression
  // entirely, i.e. the expression is implicitly wrapped with ^ and $.
  string test_id_regexp = 1;

  // A test exoneration must have a variant satisfying this predicate.
  VariantPredicate variant = 2;
}

// Represents a function Variant -> bool.
message VariantPredicate {
  oneof predicate {
    // A variant must be equal this definition exactly.
    Variant equals = 1;

    // A variant's key-value pairs must contain those in this one.
    Variant contains = 2;
  }
}

// Represents a function Artifact -> bool.
message ArtifactPredicate {
  // A set of Invocation's outgoing edge types.
  message EdgeTypeSet {
    // The edges represented by Invocation.included_invocations field.
    bool included_invocations = 1;
    // The parent-child relationship between Invocation and TestResult.
    bool test_results = 2;
  }

  // Specifies which edges to follow when retrieving directly/indirectly
  // included artifacts.
  // For example,
  // - to retrieve only invocation-level artifacts, use
  //   {included_invocations: true}.
  // - to retrieve only test-result-level artifacts, use {test_results: true}.
  //
  // By default, follows all edges.
  EdgeTypeSet follow_edges = 1; // defaults to All.

  // If an Artifact belongs to a TestResult, then the test result must satisfy
  // this predicate.
  // Note: this predicate does NOT apply to invocation-level artifacts.
  // To exclude them from the response, use follow_edges.
  TestResultPredicate test_result_predicate = 2;

  // An artifact must have a content type matching this regular expression
  // entirely, i.e. the expression is implicitly wrapped with ^ and $.
  // Defaults to ".*".
  string content_type_regexp = 3;

  // An artifact must have an ID matching this regular expression entirely, i.e.
  // the expression is implicitly wrapped with ^ and $.  Defaults to ".*".
  string artifact_id_regexp = 4;
}


// Represents a function TestMetadata -> bool.
// Empty message matches all test metadata.
message TestMetadataPredicate {
  // A test metadata must have the test id in this list.
  repeated string test_ids = 1;
}
