1 /* 2 * Copyright (C) 2022 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.compatibility.common.tradefed.result.suite; 17 18 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 19 import com.android.tradefed.config.Option; 20 import com.android.tradefed.config.OptionClass; 21 import com.android.tradefed.invoker.IInvocationContext; 22 import com.android.tradefed.invoker.InvocationContext; 23 import com.android.tradefed.invoker.tracing.CloseableTraceScope; 24 import com.android.tradefed.log.LogUtil.CLog; 25 import com.android.tradefed.result.ITestInvocationListener; 26 import com.android.tradefed.result.ITestSummaryListener; 27 import com.android.tradefed.result.proto.FileProtoResultReporter; 28 import com.android.tradefed.result.proto.ProtoResultParser; 29 import com.android.tradefed.util.FileUtil; 30 import com.android.tradefed.util.IDisableable; 31 32 import java.io.File; 33 import java.io.IOException; 34 35 /** 36 * This reporter compacts together all the partial proto to save disk space. This is a memory heavy 37 * operation so it's executed last and can optionally fail and be inop (resulting in no 38 * compression). 39 */ 40 @OptionClass(alias = "result-reporter") 41 public class CompactProtoReporter 42 implements ITestInvocationListener, ITestSummaryListener, IDisableable { 43 44 @Option( 45 name = "skip-proto-compacting", 46 description = "Option to disable compacting the protos at the end") 47 private boolean mSkipProtoCompacting = false; 48 49 @Option(name = "disable", description = "Whether or not to disable this reporter.") 50 private boolean mDisable = false; 51 52 private CompatibilityBuildHelper mBuildHelper; 53 54 /** The directory containing the proto results */ 55 private File mResultDir = null; 56 57 private File mBaseProtoFile = null; 58 59 @Override invocationStarted(IInvocationContext context)60 public void invocationStarted(IInvocationContext context) { 61 if (mBuildHelper == null) { 62 mBuildHelper = new CompatibilityBuildHelper(context.getBuildInfos().get(0)); 63 mResultDir = CompatibilityProtoResultReporter.getProtoResultDirectory(mBuildHelper); 64 mBaseProtoFile = new File(mResultDir, CompatibilityProtoResultReporter.PROTO_FILE_NAME); 65 } 66 } 67 68 @Override invocationEnded(long elapsedTime)69 public void invocationEnded(long elapsedTime) { 70 if (mSkipProtoCompacting) { 71 return; 72 } 73 if (mBuildHelper == null) { 74 CLog.w("Something went wrong and no build helper are configured."); 75 return; 76 } 77 // Compact all the protos 78 try (CloseableTraceScope ignored = new CloseableTraceScope("compact_protos")) { 79 CLog.d("Compacting protos to reduce disk size"); 80 compactAllProtos(); 81 CLog.d("Done compacting protos"); 82 } catch (RuntimeException e) { 83 CLog.e("Failed to compact the protos"); 84 CLog.e(e); 85 FileUtil.deleteFile(mBaseProtoFile); 86 return; 87 } 88 // Delete all the protos we compacted 89 int index = 0; 90 while (new File(mBaseProtoFile.getAbsolutePath() + index).exists()) { 91 FileUtil.deleteFile(new File(mBaseProtoFile.getAbsolutePath() + index)); 92 index++; 93 } 94 } 95 compactAllProtos()96 private void compactAllProtos() { 97 FileProtoResultReporter fprr = new FileProtoResultReporter(); 98 fprr.setFileOutput(mBaseProtoFile); 99 ProtoResultParser parser = new ProtoResultParser(fprr, new InvocationContext(), true); 100 int index = 0; 101 while (new File(mBaseProtoFile.getAbsolutePath() + index).exists()) { 102 try { 103 parser.processFileProto(new File(mBaseProtoFile.getAbsolutePath() + index)); 104 } catch (IOException e) { 105 throw new RuntimeException(e); 106 } 107 index++; 108 } 109 } 110 111 @Override isDisabled()112 public boolean isDisabled() { 113 return mDisable; 114 } 115 } 116