go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/resultdb/proto/v1/test_result.proto (about) 1 // Copyright 2019 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 syntax = "proto3"; 16 17 package luci.resultdb.v1; 18 19 import "google/api/field_behavior.proto"; 20 import "google/protobuf/duration.proto"; 21 import "google/protobuf/struct.proto"; 22 import "google/protobuf/timestamp.proto"; 23 import "go.chromium.org/luci/resultdb/proto/v1/common.proto"; 24 import "go.chromium.org/luci/resultdb/proto/v1/test_metadata.proto"; 25 import "go.chromium.org/luci/resultdb/proto/v1/failure_reason.proto"; 26 27 option go_package = "go.chromium.org/luci/resultdb/proto/v1;resultpb"; 28 29 // A result of a functional test case. 30 // Often a single test case is executed multiple times and has multiple results, 31 // a single test suite has multiple test cases, 32 // and the same test suite can be executed in different variants 33 // (OS, GPU, compile flags, etc). 34 // 35 // This message does not specify the test id. 36 // It should be available in the message that embeds this message. 37 // 38 // Next id: 17. 39 message TestResult { 40 reserved 11; // test_location 41 42 // Can be used to refer to this test result, e.g. in ResultDB.GetTestResult 43 // RPC. 44 // Format: 45 // "invocations/{INVOCATION_ID}/tests/{URL_ESCAPED_TEST_ID}/results/{RESULT_ID}". 46 // where URL_ESCAPED_TEST_ID is test_id escaped with 47 // https://golang.org/pkg/net/url/#PathEscape See also https://aip.dev/122. 48 // 49 // Output only. 50 string name = 1 [ 51 (google.api.field_behavior) = OUTPUT_ONLY, 52 (google.api.field_behavior) = IMMUTABLE 53 ]; 54 55 // Test id, a unique identifier of the test in a LUCI project. 56 // Regex: ^[[::print::]]{1,512}$ 57 // 58 // If two tests have a common test id prefix that ends with a 59 // non-alphanumeric character, they considered a part of a group. Examples: 60 // - "a/b/c" 61 // - "a/b/d" 62 // - "a/b/e:x" 63 // - "a/b/e:y" 64 // - "a/f" 65 // This defines the following groups: 66 // - All items belong to one group because of the common prefix "a/" 67 // - Within that group, the first 4 form a sub-group because of the common 68 // prefix "a/b/" 69 // - Within that group, "a/b/e:x" and "a/b/e:y" form a sub-group because of 70 // the common prefix "a/b/e:". 71 // This can be used in UI. 72 // LUCI does not interpret test ids in any other way. 73 string test_id = 2 [(google.api.field_behavior) = IMMUTABLE]; 74 75 // Identifies a test result in a given invocation and test id. 76 // Regex: ^[a-z0-9\-_.]{1,32}$ 77 string result_id = 3 [ 78 (google.api.field_behavior) = IMMUTABLE, 79 (google.api.field_behavior) = REQUIRED 80 ]; 81 82 // Description of one specific way of running the test, 83 // e.g. a specific bucket, builder and a test suite. 84 Variant variant = 4 [(google.api.field_behavior) = IMMUTABLE]; 85 86 // Whether the result of test case execution is expected. 87 // In a typical Chromium CL, 99%+ of test results are expected. 88 // Users are typically interested only in the unexpected results. 89 // 90 // An unexpected result != test case failure. There are test cases that are 91 // expected to fail/skip/crash. The test harness compares the actual status 92 // with the expected one(s) and this field is the result of the comparison. 93 bool expected = 5 [(google.api.field_behavior) = IMMUTABLE]; 94 95 // Machine-readable status of the test case. 96 // MUST NOT be STATUS_UNSPECIFIED. 97 TestStatus status = 6 [(google.api.field_behavior) = IMMUTABLE]; 98 99 // Human-readable explanation of the result, in HTML. 100 // MUST be sanitized before rendering in the browser. 101 // 102 // The size of the summary must be equal to or smaller than 4096 bytes in 103 // UTF-8. 104 // 105 // Supports artifact embedding using custom tags: 106 // * <text-artifact> renders contents of an artifact as text. 107 // Usage: 108 // * To embed result level artifact: <text-artifact 109 // artifact-id="<artifact_id>"> 110 // * To embed invocation level artifact: <text-artifact 111 // artifact-id="<artifact_id>" inv-level> 112 string summary_html = 7 [(google.api.field_behavior) = IMMUTABLE]; 113 114 // The point in time when the test case started to execute. 115 google.protobuf.Timestamp start_time = 8 116 [(google.api.field_behavior) = IMMUTABLE]; 117 118 // Duration of the test case execution. 119 // MUST be equal to or greater than 0. 120 google.protobuf.Duration duration = 9 121 [(google.api.field_behavior) = IMMUTABLE]; 122 123 // Metadata for this test result. 124 // It might describe this particular execution or the test case. 125 // A key can be repeated. 126 repeated StringPair tags = 10 [(google.api.field_behavior) = IMMUTABLE]; 127 128 // Hash of the variant. 129 // hex(sha256(sorted(''.join('%s:%s\n' for k, v in variant.items())))). 130 // 131 // Output only. 132 string variant_hash = 12 [ 133 (google.api.field_behavior) = OUTPUT_ONLY, 134 (google.api.field_behavior) = IMMUTABLE 135 ]; 136 137 // Information about the test at the time of its execution. 138 TestMetadata test_metadata = 13; 139 140 // Information about the test failure. Only present if the test failed. 141 FailureReason failure_reason = 14; 142 143 // Arbitrary JSON object that contains structured, domain-specific properties 144 // of the test result. 145 // 146 // The serialized size must be <= 4096 bytes. 147 google.protobuf.Struct properties = 15; 148 149 // Whether the test result has been masked so that it includes only metadata. 150 // The metadata fields for a TestResult are: 151 // * name 152 // * test_id 153 // * result_id 154 // * expected 155 // * status 156 // * start_time 157 // * duration 158 // * variant_hash 159 // * failure_reason.primary_error_message (truncated to 140 characters) 160 // * skip_reason 161 // 162 // Output only. 163 bool is_masked = 16 [(google.api.field_behavior) = OUTPUT_ONLY]; 164 165 // Reasoning behind a test skip, in machine-readable form. 166 // Used to assist downstream analyses, such as automatic bug-filing. 167 // MUST not be set unless status is SKIP. 168 SkipReason skip_reason = 18; 169 } 170 171 // Machine-readable status of a test result. 172 enum TestStatus { 173 // Status was not specified. 174 // Not to be used in actual test results; serves as a default value for an 175 // unset field. 176 STATUS_UNSPECIFIED = 0; 177 178 // The test case has passed. 179 PASS = 1; 180 181 // The test case has failed. 182 // Suggests that the code under test is incorrect, but it is also possible 183 // that the test is incorrect or it is a flake. 184 FAIL = 2; 185 186 // The test case has crashed during execution. 187 // The outcome is inconclusive: the code under test might or might not be 188 // correct, but the test+code is incorrect. 189 CRASH = 3; 190 191 // The test case has started, but was aborted before finishing. 192 // A common reason: timeout. 193 ABORT = 4; 194 195 // The test case did not execute. 196 // Examples: 197 // - The execution of the collection of test cases, such as a test 198 // binary, was aborted prematurely and execution of some test cases was 199 // skipped. 200 // - The test harness configuration specified that the test case MUST be 201 // skipped. 202 SKIP = 5; 203 } 204 205 // Machine-readable reason that a test execution was skipped. 206 // Only reasons actually used are listed here, if you need a new reason 207 // please add it here and send a CL to the OWNERS. 208 enum SkipReason { 209 // Skip reason was not specified. 210 // This represents an unset field which should be used for non-skip test 211 // result statuses. It can also be used if none of the other statuses 212 // apply. 213 SKIP_REASON_UNSPECIFIED = 0; 214 215 // Disabled automatically in response to a test skipping policy that skips 216 // flaky tests. 217 // Used for ChromeOS CQ test filtering. 218 AUTOMATICALLY_DISABLED_FOR_FLAKINESS = 1; 219 } 220 221 // Indicates the test subject (e.g. a CL) is absolved from blame 222 // for an unexpected result of a test variant. 223 // For example, the test variant fails both with and without CL, so it is not 224 // CL's fault. 225 message TestExoneration { 226 // Can be used to refer to this test exoneration, e.g. in 227 // ResultDB.GetTestExoneration RPC. 228 // Format: 229 // invocations/{INVOCATION_ID}/tests/{URL_ESCAPED_TEST_ID}/exonerations/{EXONERATION_ID}. 230 // URL_ESCAPED_TEST_ID is test_variant.test_id escaped with 231 // https://golang.org/pkg/net/url/#PathEscape See also https://aip.dev/122. 232 // 233 // Output only. 234 string name = 1 [ 235 (google.api.field_behavior) = OUTPUT_ONLY, 236 (google.api.field_behavior) = IMMUTABLE 237 ]; 238 239 // Test identifier, see TestResult.test_id. 240 string test_id = 2; 241 242 // Description of the variant of the test, see Variant type. 243 // Unlike TestResult.extra_variant_pairs, this one must be a full definition 244 // of the variant, i.e. it is not combined with Invocation.base_test_variant. 245 Variant variant = 3; 246 247 // Identifies an exoneration in a given invocation and test id. 248 // It is server-generated. 249 string exoneration_id = 4 [ 250 (google.api.field_behavior) = OUTPUT_ONLY, 251 (google.api.field_behavior) = IMMUTABLE 252 ]; 253 254 // Reasoning behind the exoneration, in HTML. 255 // MUST be sanitized before rendering in the browser. 256 string explanation_html = 5 [(google.api.field_behavior) = IMMUTABLE]; 257 258 // Hash of the variant. 259 // hex(sha256(sorted(''.join('%s:%s\n' for k, v in variant.items())))). 260 string variant_hash = 6 [(google.api.field_behavior) = IMMUTABLE]; 261 262 // Reasoning behind the exoneration, in machine-readable form. 263 // Used to assist downstream analyses, such as automatic bug-filing. 264 // This allow detection of e.g. critical tests failing in presubmit, 265 // even if they are being exonerated because they fail on other CLs. 266 ExonerationReason reason = 7 [(google.api.field_behavior) = IMMUTABLE]; 267 268 // Whether the test exoneration has been masked so that it includes only 269 // metadata. The metadata fields for a TestExoneration are: 270 // * name 271 // * test_id 272 // * exoneration_id 273 // * variant_hash 274 // * explanation_html 275 // * reason 276 // 277 // Output only. 278 bool is_masked = 8 [(google.api.field_behavior) = OUTPUT_ONLY]; 279 } 280 281 // Reason why a test variant was exonerated. 282 enum ExonerationReason { 283 // Reason was not specified. 284 // Not to be used in actual test exonerations; serves as a default value for 285 // an unset field. 286 EXONERATION_REASON_UNSPECIFIED = 0; 287 288 // Similar unexpected results were observed on a mainline branch 289 // (i.e. against a build without unsubmitted changes applied). 290 // (For avoidance of doubt, this includes both flakily and 291 // deterministically occurring unexpected results.) 292 // Applies to unexpected results in presubmit/CQ runs only. 293 OCCURS_ON_MAINLINE = 1; 294 295 // Similar unexpected results were observed in presubmit run(s) for other, 296 // unrelated CL(s). (This is suggestive of the issue being present 297 // on mainline but is not confirmed as there are possible confounding 298 // factors, like how tests are run on CLs vs how tests are run on 299 // mainline branches.) 300 // Applies to unexpected results in presubmit/CQ runs only. 301 OCCURS_ON_OTHER_CLS = 2; 302 303 // The tests are not critical to the test subject (e.g. CL) passing. 304 // This could be because more data is being collected to determine if 305 // the tests are stable enough to be made critical (as is often the 306 // case for experimental test suites). 307 // If information exists indicating the tests are producing unexpected 308 // results, and the tests are not critical for that reason, 309 // prefer more specific reasons OCCURS_ON_MAINLINE or OCCURS_ON_OTHER_CLS. 310 NOT_CRITICAL = 3; 311 312 // The test result was an unexpected pass. (Note that such an exoneration is 313 // not automatically created for unexpected passes, unless the option is 314 // specified to ResultSink or the project manually creates one). 315 UNEXPECTED_PASS = 4; 316 }