• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.proto;
17 
18 import com.android.tradefed.invoker.IInvocationContext;
19 import com.android.tradefed.invoker.InvocationContext;
20 import com.android.tradefed.invoker.proto.InvocationContext.Context;
21 import com.android.tradefed.log.LogUtil.CLog;
22 import com.android.tradefed.result.proto.TestRecordProto.TestRecord;
23 import com.android.tradefed.result.proto.TestRecordProto.TestStatus;
24 import com.android.tradefed.util.proto.TestRecordProtoUtil;
25 
26 import com.google.common.base.Strings;
27 import com.google.protobuf.Any;
28 
29 import java.io.File;
30 import java.io.IOException;
31 import java.util.HashMap;
32 import java.util.Map;
33 
34 /**
35  * A result reporter meant to report only the module level results. No re-entry is supported in this
36  * module. The intent of this reporter is primarily for caching at module level.
37  */
38 public class ModuleProtoResultReporter extends FileProtoResultReporter {
39 
40     public static final String INVOCATION_ID_KEY = "invocation_id";
41     private boolean mStopCache = false;
42     private String mInvocationId = null;
43     private boolean mGranularResults = false;
44 
ModuleProtoResultReporter()45     public ModuleProtoResultReporter() {
46         setPeriodicWriting(false);
47         setDelimitedOutput(false);
48     }
49 
ModuleProtoResultReporter( IInvocationContext mainInvocationContext, boolean granularResults)50     public ModuleProtoResultReporter(
51             IInvocationContext mainInvocationContext, boolean granularResults) {
52         this();
53         copyAttributes(mainInvocationContext);
54         mGranularResults = granularResults;
55     }
56 
57     @Override
beforeModuleStart()58     protected void beforeModuleStart() {
59         IInvocationContext stubContext = createCachedContext();
60         invocationStarted(stubContext);
61     }
62 
63     @Override
afterModuleEnd()64     protected void afterModuleEnd() {
65         invocationEnded(0);
66     }
67 
68     @Override
processTestCaseEnded(TestRecord testCaseRecord)69     public void processTestCaseEnded(TestRecord testCaseRecord) {
70         if (mGranularResults) {
71             super.processTestCaseEnded(testCaseRecord);
72         }
73         if (testCaseRecord.getStatus().equals(TestStatus.FAIL)) {
74             reportStopCaching();
75         }
76     }
77 
78     @Override
processTestRunEnded(TestRecord runRecord, boolean moduleInProgress)79     public void processTestRunEnded(TestRecord runRecord, boolean moduleInProgress) {
80         if (mGranularResults) {
81             super.processTestRunEnded(runRecord, moduleInProgress);
82         }
83         if (runRecord.hasDebugInfo()) {
84             reportStopCaching();
85         }
86     }
87 
88     @Override
processTestModuleEnd(TestRecord moduleRecord)89     public void processTestModuleEnd(TestRecord moduleRecord) {
90         super.processTestModuleEnd(moduleRecord);
91         if (moduleRecord.hasSkipReason()) {
92             reportStopCaching();
93         }
94     }
95 
stopCaching()96     public boolean stopCaching() {
97         return mStopCache;
98     }
99 
reportStopCaching()100     public void reportStopCaching() {
101         mStopCache = true;
102     }
103 
reportGranularResults()104     public boolean reportGranularResults() {
105         return mGranularResults;
106     }
107 
createCachedContext()108     protected IInvocationContext createCachedContext() {
109         IInvocationContext stubContext = new InvocationContext();
110         if (mInvocationId != null) {
111             CLog.d("Copying property into module results: %s", mInvocationId);
112             stubContext.addInvocationAttribute(INVOCATION_ID_KEY, mInvocationId);
113         }
114         return stubContext;
115     }
116 
copyAttributes(IInvocationContext mainContext)117     private void copyAttributes(IInvocationContext mainContext) {
118         String invocationId = mainContext.getAttribute(INVOCATION_ID_KEY);
119         if (!Strings.isNullOrEmpty(invocationId)) {
120             mInvocationId = invocationId;
121         }
122     }
123 
124     /** Parsing util to extract metadata we might have transferred */
parseResultsMetadata(File protoResults)125     public static Map<String, String> parseResultsMetadata(File protoResults) {
126         if (protoResults == null) {
127             CLog.w("Proto result file is null, cannot parse it.");
128             return new HashMap<>();
129         }
130         try {
131             TestRecord record = TestRecordProtoUtil.readFromFile(protoResults, false);
132             Any anyDescription = record.getDescription();
133             if (!anyDescription.is(Context.class)) {
134                 throw new RuntimeException("Expected Any description of type Context");
135             }
136             IInvocationContext receivedContext =
137                     InvocationContext.fromProto(anyDescription.unpack(Context.class));
138             Map<String, String> receivedAttributes = receivedContext.getAttributes().getUniqueMap();
139             CLog.d("Attributes received from cached results: %s", receivedAttributes);
140             return receivedAttributes;
141         } catch (IOException | RuntimeException e) {
142             CLog.e(e);
143         }
144         return new HashMap<>();
145     }
146 }
147