1 /* 2 * Copyright (C) 2014 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 17 package com.android.tradefed.result; 18 19 import com.android.tradefed.config.Option; 20 import com.android.tradefed.device.DeviceNotAvailableException; 21 import com.android.tradefed.device.IFileEntry; 22 import com.android.tradefed.device.ITestDevice; 23 import com.android.tradefed.log.LogUtil.CLog; 24 import com.android.tradefed.testtype.IDeviceTest; 25 import com.android.tradefed.testtype.IRemoteTest; 26 27 import java.util.LinkedHashMap; 28 import java.util.Map; 29 30 /** 31 * Helper test component that pulls files located on a device and adds them to the test logs. 32 * The component provides {@link IRemoteTest} and {@link IDeviceTest} services. 33 * <p> 34 * The path to files on the device is specified with upload-dir or upload-pattern options. 35 * The files will be removed if clean-upload-pattern option is provided. 36 */ 37 public class LogFilesReporter implements IRemoteTest, IDeviceTest { 38 39 @Option(name = "upload-pattern", 40 description = "A path pattern of files on the device to be added to the test logs.") 41 private String mUploadPattern = null; 42 43 // TODO(mdzyuba): upload-pattern does not work at the moment. Remove upload-dir once resolved. 44 @Option(name = "upload-dir", 45 description = "A folder on the device to be added to the test logs.") 46 private String mUploadDir = null; 47 48 @Option(name = "clean-upload-pattern", 49 description = "Clean files specified in \"upload-pattern\" after the test is done.") 50 private boolean mRemoveFilesSpecifiedByUploadPattern = true; 51 52 // A device instance. 53 private ITestDevice mDevice; 54 55 /** 56 * {@inheritDoc} 57 */ 58 @Override 59 public void setDevice(ITestDevice device) { 60 mDevice = device; 61 } 62 63 /** 64 * {@inheritDoc} 65 */ 66 @Override 67 public ITestDevice getDevice() { 68 return mDevice; 69 } 70 71 /** 72 * {@inheritDoc} 73 */ 74 @Override 75 public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { 76 if (mUploadPattern != null) { 77 uploadFilesOnDeviceToLogs(mUploadPattern, listener); 78 if (mRemoveFilesSpecifiedByUploadPattern) { 79 cleanFilesOnDevice(mUploadPattern); 80 } 81 } 82 if (mUploadDir != null) { 83 uploadFolderOnDeviceToLogs(mUploadDir, listener); 84 if (mRemoveFilesSpecifiedByUploadPattern) { 85 cleanFilesOnDevice(mUploadDir + "/*"); 86 } 87 } 88 } 89 90 /** 91 * Uploads files from a device to test logs. 92 * 93 * @param filesPattern a path pattern to files on device to be added to the logs. 94 * @param listener a listener for test results from the test invocation. 95 * @throws DeviceNotAvailableException in case device is unavailable. 96 */ 97 protected void uploadFilesOnDeviceToLogs(String filesPattern, ITestInvocationListener listener) 98 throws DeviceNotAvailableException { 99 final DeviceFileReporter reporter = new DeviceFileReporter(getDevice(), listener); 100 reporter.addPatterns(filesPattern); 101 reporter.run(); 102 } 103 104 /** 105 * Uploads files from a device to test logs. 106 * 107 * @param dir a full path to a folder on device containing files to be added to the logs. 108 * @param listener a listener for test results from the test invocation. 109 * @throws DeviceNotAvailableException in case device is unavailable. 110 */ 111 protected void uploadFolderOnDeviceToLogs(String dir, ITestInvocationListener listener) 112 throws DeviceNotAvailableException { 113 final DeviceFileReporter reporter = new DeviceFileReporter(getDevice(), listener); 114 Map<String, LogDataType> uploadFilePatterns = new LinkedHashMap<String, LogDataType>(); 115 IFileEntry outputDir = getDevice().getFileEntry(dir); 116 if (outputDir != null) { 117 for (IFileEntry file : outputDir.getChildren(false)) { 118 LogDataType logDataType = LogDataType.UNKNOWN; 119 if (file.getName().endsWith(LogDataType.PNG.getFileExt())) { 120 logDataType = LogDataType.PNG; 121 } else if (file.getName().endsWith(LogDataType.XML.getFileExt())) { 122 logDataType = LogDataType.XML; 123 } 124 CLog.v(String.format("Adding file %s", file.getFullPath())); 125 uploadFilePatterns.put(file.getFullPath(), logDataType); 126 } 127 reporter.addPatterns(uploadFilePatterns); 128 reporter.run(); 129 } else { 130 CLog.w("Directory not found on device: %s", dir); 131 } 132 } 133 134 /** 135 * Cleans the files on the device. 136 * 137 * @param pattern a path pattern to files to be removed. 138 * @throws DeviceNotAvailableException in case device is unavailable. 139 */ 140 protected void cleanFilesOnDevice(String pattern) throws DeviceNotAvailableException { 141 String folder = pattern.substring(0, pattern.lastIndexOf('/')); 142 if (doesDirectoryExistOnDevice(folder)) { 143 getDevice().executeShellCommand(String.format("rm %s", pattern)); 144 } 145 } 146 147 /** 148 * Checks to see if a directory exists on a device. 149 * 150 * @param folder a full path to a directory on a device to be verified. 151 * @return true if a directory exists, false otherwise. 152 * @throws DeviceNotAvailableException in case device is unavailable. 153 */ 154 protected boolean doesDirectoryExistOnDevice(String folder) throws DeviceNotAvailableException { 155 IFileEntry outputDir = getDevice().getFileEntry(folder); 156 if (outputDir == null) { 157 CLog.w("Directory not found on device: %s", folder); 158 return false; 159 } 160 return true; 161 } 162 } 163