1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.tradefed.result;
17 
18 import com.android.tradefed.result.error.ErrorIdentifier;
19 import com.android.tradefed.result.proto.TestRecordProto;
20 
21 import javax.annotation.Nullable;
22 
23 /**
24  * The class describing a failure information in Trade Federation. This class contains the debugging
25  * information and context of the failure that helps understanding the issue.
26  */
27 public class FailureDescription {
28     // The error message generated from the failure
29     private String mErrorMessage;
30     // Optional: The category of the failure
31     private @Nullable TestRecordProto.FailureStatus mFailureStatus =
32             TestRecordProto.FailureStatus.UNSET;
33     // Optional: Context of the action in progress during the failure
34     private @Nullable ActionInProgress mActionInProgress = ActionInProgress.UNSET;
35     // Optional: A free-formed text that help debugging the failure
36     private @Nullable String mDebugHelpMessage = null;
37     // Optional: The exception that triggered the failure
38     private @Nullable Throwable mCause = null;
39     // Whether or not the error is retriable by Tradefed auto-retry. By Default we retry it all.
40     private boolean mRetriable = true;
41 
42     // Error identifiers
43     // Optional: The error identifier and its code
44     private @Nullable ErrorIdentifier mErrorId = null;
45     // Optional: The class that raised the error
46     private @Nullable String mOrigin = null;
47 
FailureDescription()48     FailureDescription() {}
49 
50     /**
51      * Set the {@link com.android.tradefed.result.proto.TestRecordProto.FailureStatus} associated
52      * with the failure.
53      */
setFailureStatus(TestRecordProto.FailureStatus status)54     public FailureDescription setFailureStatus(TestRecordProto.FailureStatus status) {
55         mFailureStatus = status;
56         return this;
57     }
58 
59     /** Returns the FailureStatus associated with the failure. Can be null. */
getFailureStatus()60     public @Nullable TestRecordProto.FailureStatus getFailureStatus() {
61         if (TestRecordProto.FailureStatus.UNSET.equals(mFailureStatus)) {
62             return null;
63         }
64         return mFailureStatus;
65     }
66 
67     /** Sets the action in progress during the failure. */
setActionInProgress(ActionInProgress action)68     public FailureDescription setActionInProgress(ActionInProgress action) {
69         mActionInProgress = action;
70         return this;
71     }
72 
73     /** Returns the action in progress during the failure. Can be null. */
getActionInProgress()74     public @Nullable ActionInProgress getActionInProgress() {
75         return mActionInProgress;
76     }
77 
78     /** Sets the debug help message for the failure. */
setDebugHelpMessage(String message)79     public FailureDescription setDebugHelpMessage(String message) {
80         mDebugHelpMessage = message;
81         return this;
82     }
83 
84     /** Returns the debug help message. Can be null. */
getDebugHelpMessage()85     public @Nullable String getDebugHelpMessage() {
86         return mDebugHelpMessage;
87     }
88 
89     /** Sets the exception that caused the failure if any. */
setCause(Throwable cause)90     public FailureDescription setCause(Throwable cause) {
91         mCause = cause;
92         return this;
93     }
94 
95     /** Returns the exception that caused the failure. Can be null. */
getCause()96     public @Nullable Throwable getCause() {
97         return mCause;
98     }
99 
100     /** Sets whether or not the failure is retriable. */
setRetriable(boolean retriable)101     public FailureDescription setRetriable(boolean retriable) {
102         mRetriable = retriable;
103         return this;
104     }
105 
106     /** Returns whether or not the error is retriable or not. */
isRetriable()107     public boolean isRetriable() {
108         return mRetriable;
109     }
110 
111     /** Sets the {@link ErrorIdentifier} representing the failure. */
setErrorIdentifier(ErrorIdentifier errorId)112     public FailureDescription setErrorIdentifier(ErrorIdentifier errorId) {
113         mErrorId = errorId;
114         return this;
115     }
116 
117     /** Returns the {@link ErrorIdentifier} representing the failure. Can be null. */
getErrorIdentifier()118     public ErrorIdentifier getErrorIdentifier() {
119         return mErrorId;
120     }
121 
122     /** Sets the origin of the error. */
setOrigin(String origin)123     public FailureDescription setOrigin(String origin) {
124         mOrigin = origin;
125         return this;
126     }
127 
128     /** Returns the origin of the error. Can be null. */
getOrigin()129     public String getOrigin() {
130         return mOrigin;
131     }
132 
133     /** Sets the error message. */
setErrorMessage(String errorMessage)134     public void setErrorMessage(String errorMessage) {
135         mErrorMessage = errorMessage;
136     }
137 
138     /** Returns the error message associated with the failure. */
getErrorMessage()139     public String getErrorMessage() {
140         return mErrorMessage;
141     }
142 
143     @Override
toString()144     public String toString() {
145         // For backward compatibility of result interface, toString falls back to the simple message
146         return mErrorMessage;
147     }
148 
149     /**
150      * Create a {@link FailureDescription} based on the error message generated from the failure.
151      *
152      * @param errorMessage The error message from the failure.
153      * @return the created {@link FailureDescription}
154      */
create(String errorMessage)155     public static FailureDescription create(String errorMessage) {
156         return create(errorMessage, null);
157     }
158 
159     /**
160      * Create a {@link FailureDescription} based on the error message generated from the failure.
161      *
162      * @param errorMessage The error message from the failure.
163      * @param status The status associated with the failure.
164      * @return the created {@link FailureDescription}
165      */
create( String errorMessage, @Nullable TestRecordProto.FailureStatus status)166     public static FailureDescription create(
167             String errorMessage, @Nullable TestRecordProto.FailureStatus status) {
168         FailureDescription info = new FailureDescription();
169         info.mErrorMessage = errorMessage;
170         info.mFailureStatus = status;
171         return info;
172     }
173 
174     @Override
hashCode()175     public int hashCode() {
176         final int prime = 31;
177         int result = 1;
178         result = prime * result + ((mActionInProgress == null) ? 0 : mActionInProgress.hashCode());
179         result = prime * result + ((mDebugHelpMessage == null) ? 0 : mDebugHelpMessage.hashCode());
180         result = prime * result + ((mErrorMessage == null) ? 0 : mErrorMessage.hashCode());
181         result = prime * result + ((mFailureStatus == null) ? 0 : mFailureStatus.hashCode());
182         return result;
183     }
184 
185     @Override
equals(Object obj)186     public boolean equals(Object obj) {
187         if (this == obj) return true;
188         if (obj == null) return false;
189         if (getClass() != obj.getClass()) return false;
190         FailureDescription other = (FailureDescription) obj;
191         if (mActionInProgress != other.mActionInProgress) return false;
192         if (mDebugHelpMessage == null) {
193             if (other.mDebugHelpMessage != null) return false;
194         } else if (!mDebugHelpMessage.equals(other.mDebugHelpMessage)) return false;
195         if (mErrorMessage == null) {
196             if (other.mErrorMessage != null) return false;
197         } else if (!mErrorMessage.equals(other.mErrorMessage)) return false;
198         if (mFailureStatus != other.mFailureStatus) return false;
199         return true;
200     }
201 }
202