/*
* Copyright (C) 2021 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 "google/api/field_behavior.proto";
import public "tools/tradefederation/core/proto/resultdb/common.proto";
import public "tools/tradefederation/core/proto/resultdb/test_metadata.proto";
import public "tools/tradefederation/core/proto/resultdb/test_result.proto";
import public "tools/tradefederation/core/proto/resultdb/test_verdict.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 matching test variant with its outcomes.
// Also known as a test verdict.
message TestVariant {
  // The structured test identifier.
  //
  // Refer to TestResult.test_id_structured for details.
  TestIdentifier test_id_structured = 11;

  // A unique identifier of the test in a LUCI project.
  // Regex: ^[[::print::]]{1,512}$
  //
  // Refer to TestResult.test_id for details.
  string test_id = 1;

  // Description of one specific way of running the test,
  // e.g. a specific bucket, builder and a test suite.
  Variant variant = 2;

  // Hash of the variant.
  // hex(sha256(sorted(''.join('%s:%s\n' for k, v in variant.items())))).
  string variant_hash = 3;

  // Deprecated: Use status_v2 and status_override.
  // Status of the test variant.
  TestVariantStatus status = 4 [ deprecated = true ];

  // Status of the test verdict (v2).
  TestVerdict.Status status_v2 = 12;

  // The status override, e.g. whether the test was exonerated.
  TestVerdict.StatusOverride status_override = 13;

  // Outcomes of the test variant.
  repeated TestResultBundle results = 5;

  // Test exonerations if any test variant is exonerated.
  repeated TestExoneration exonerations = 6;

  // Information about the test at the time of its execution.
  //
  // All test results of the same test variant should report the same test
  // metadata. This RPC relies on this rule and returns test metadata from
  // *arbitrary* result of the test variant.
  TestMetadata test_metadata = 7;

  // Whether the
  //    - test metadata; or
  //    - the variant definition; or
  //    - both the test metadata and variant definition
  // have been masked from the test variant.
  //
  // Output only.
  bool is_masked = 8 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The identity of the code sources tested. This ID can be used
  // to lookup of the actual sources in QueryTestVariantsResponse.sources.
  //
  // All test results of the same test variant should be attached to the same
  // sources (via their respective invocation(s)). This RPC relies upon this
  // and returns sources from an *arbitrary* result of the test variant.
  //
  // If the code sources tested are not available, this field is blank.
  string sources_id = 9;

  // Contain the data for instruction for the test verdict.
  // To find out the instruction for a test verdict, we select an *arbitrary*
  // test result in the test verdict and get its instruction.
  // Note: If in this test verdict, if there are different instructions for
  // test result, the result may be undeterministic.
  VerdictInstruction instruction = 10;
}

message VerdictInstruction {
  // Name of the instruction.
  // Format: invocations/<invocation id>/instructions/<instruction id>
  string instruction = 1;
}

// Outcomes of an execution of the test variant.
message TestResultBundle {
  // Result of the test variant execution.
  TestResult result = 1;
}

// Status of a test variant.
// References to test statuses in the description refer to legacy
// status values, not status_v2.
// DEPRECATED: Use luci.resultdb.v1.TestVerdict.Status instead.
enum TestVariantStatus {
  // a test variant must not have this status.
  // This is only used when filtering variants.
  TEST_VARIANT_STATUS_UNSPECIFIED = 0;
  // The test variant has no exonerations, and all results are unexpected.
  UNEXPECTED = 10;
  // The test variant has no exonerations, and all results are unexpectedly skipped.
  UNEXPECTEDLY_SKIPPED = 20;
  // The test variant has no exonerations, and has both expected and unexpected
  // results.
  FLAKY = 30;
  // The test variant has one or more test exonerations.
  EXONERATED = 40;
  // A special value that matches any test variant which doesn't have the status
  // EXPECTED. This includes all the above statuses. It will never be present on
  // returned results, it's only for use in predicates.
  UNEXPECTED_MASK = 45;
  // The test variant has no exonerations, and all results are expected.
  EXPECTED = 50;
}

// Represents a function TestVariant -> bool.
// Empty message matches all test variants.
message TestVariantPredicate {
  // A test variant must have this status.
  TestVariantStatus status = 1;
}

// The outcome of a test variant in a test run (a single invocation,
// excluding any included invocations).
message RunTestVerdict {
  // A unique identifier of the test in a LUCI project.
  // Regex: ^[[::print::]]{1,256}$
  //
  // Refer to TestResult.test_id for details.
  string test_id = 1;

  // Description of one specific way of running the test,
  // e.g. a specific bucket, builder and a test suite.
  Variant variant = 2;

  // Hash of the variant.
  // hex(sha256(sorted(''.join('%s:%s\n' for k, v in variant.items())))).
  string variant_hash = 3;

  // Outcomes of the test variant.
  repeated TestResultBundle results = 4;

  // Information about the test at the time of its execution.
  //
  // All test results of the same test variant should report the same test
  // metadata. This RPC relies on this rule and returns test metadata from
  // *arbitrary* result of the test variant.
  TestMetadata test_metadata = 5;
}
