• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.sandbox;
17 
18 import com.android.ddmlib.Log.LogLevel;
19 import com.android.tradefed.config.Configuration;
20 import com.android.tradefed.config.ConfigurationException;
21 import com.android.tradefed.config.GlobalConfiguration;
22 import com.android.tradefed.config.IConfiguration;
23 import com.android.tradefed.config.IDeviceConfiguration;
24 import com.android.tradefed.config.SandboxConfigurationFactory;
25 import com.android.tradefed.device.IDeviceSelection;
26 import com.android.tradefed.log.FileLogger;
27 import com.android.tradefed.log.ILeveledLogOutput;
28 import com.android.tradefed.result.ITestInvocationListener;
29 import com.android.tradefed.result.SubprocessResultsReporter;
30 import com.android.tradefed.result.proto.StreamProtoResultReporter;
31 import com.android.tradefed.util.StreamUtil;
32 
33 import java.io.File;
34 import java.io.IOException;
35 import java.io.PrintWriter;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.Set;
41 
42 /**
43  * Runner class that creates a {@link IConfiguration} based on a command line and dump it to a file.
44  * args: <DumpCmd> <output File> <remaing command line>
45  */
46 public class SandboxConfigDump {
47 
48     public enum DumpCmd {
49         /** The full xml based on the command line will be outputted */
50         FULL_XML,
51         /** Only non-versioned element of the xml will be outputted */
52         NON_VERSIONED_CONFIG,
53         /** A run-ready config will be outputted */
54         RUN_CONFIG,
55         /** Special mode that allows the sandbox to generate another layer of sandboxing. */
56         TEST_MODE,
57     }
58 
59     /**
60      * We do not output the versioned elements to avoid causing the parent process to have issues
61      * with them when trying to resolve them
62      */
63     public static final Set<String> VERSIONED_ELEMENTS = new HashSet<>();
64 
65     static {
66         VERSIONED_ELEMENTS.add(Configuration.SYSTEM_STATUS_CHECKER_TYPE_NAME);
67         VERSIONED_ELEMENTS.add(Configuration.DEVICE_METRICS_COLLECTOR_TYPE_NAME);
68         VERSIONED_ELEMENTS.add(Configuration.MULTI_PRE_TARGET_PREPARER_TYPE_NAME);
69         VERSIONED_ELEMENTS.add(Configuration.MULTI_PREPARER_TYPE_NAME);
70         VERSIONED_ELEMENTS.add(Configuration.TARGET_PREPARER_TYPE_NAME);
71         VERSIONED_ELEMENTS.add(Configuration.TEST_TYPE_NAME);
72     }
73 
74     /**
75      * Parse the args and creates a {@link IConfiguration} from it then dumps it to the result file.
76      */
parse(String[] args)77     public int parse(String[] args) {
78         // TODO: add some more checking
79         List<String> argList = new ArrayList<>(Arrays.asList(args));
80         DumpCmd cmd = DumpCmd.valueOf(argList.remove(0));
81         File resFile = new File(argList.remove(0));
82         SandboxConfigurationFactory factory = SandboxConfigurationFactory.getInstance();
83         PrintWriter pw = null;
84         try {
85             IConfiguration config =
86                     factory.createConfigurationFromArgs(argList.toArray(new String[0]), cmd);
87             if (DumpCmd.RUN_CONFIG.equals(cmd) || DumpCmd.TEST_MODE.equals(cmd)) {
88                 config.getCommandOptions().setShouldUseSandboxing(false);
89                 config.getConfigurationDescription().setSandboxed(true);
90                 // Set the reporter
91                 ITestInvocationListener reporter = null;
92                 if (getSandboxOptions(config).shouldUseProtoReporter()) {
93                     reporter = new StreamProtoResultReporter();
94                 } else {
95                     reporter = new SubprocessResultsReporter();
96                     ((SubprocessResultsReporter) reporter).setOutputTestLog(true);
97                 }
98                 config.setTestInvocationListener(reporter);
99                 // Set log level for sandbox
100                 ILeveledLogOutput logger = config.getLogOutput();
101                 logger.setLogLevel(LogLevel.VERBOSE);
102                 if (logger instanceof FileLogger) {
103                     // Ensure we get the stdout logging in FileLogger case.
104                     ((FileLogger) logger).setLogLevelDisplay(LogLevel.VERBOSE);
105                 }
106                 // Turn off some of the invocation level options that would be duplicated in the
107                 // parent.
108                 config.getCommandOptions().setBugreportOnInvocationEnded(false);
109                 config.getCommandOptions().setBugreportzOnInvocationEnded(false);
110 
111                 // Ensure in special conditions (placeholder devices) we can still allocate.
112                 secureDeviceAllocation(config);
113             }
114             if (DumpCmd.TEST_MODE.equals(cmd)) {
115                 // We allow one more layer of sandbox to be generated
116                 config.getCommandOptions().setShouldUseSandboxing(true);
117                 config.getConfigurationDescription().setSandboxed(false);
118                 // Ensure we turn off test mode afterward to avoid infinite sandboxing
119                 config.getCommandOptions().setUseSandboxTestMode(false);
120             }
121             pw = new PrintWriter(resFile);
122             if (DumpCmd.NON_VERSIONED_CONFIG.equals(cmd)) {
123                 // Remove elements that are versioned.
124                 config.dumpXml(pw, new ArrayList<>(VERSIONED_ELEMENTS));
125             } else {
126                 // FULL_XML in that case.
127                 config.dumpXml(pw);
128             }
129         } catch (ConfigurationException | IOException e) {
130             e.printStackTrace();
131             return 1;
132         } finally {
133             StreamUtil.close(pw);
134         }
135         return 0;
136     }
137 
main(final String[] mainArgs)138     public static void main(final String[] mainArgs) {
139         try {
140             GlobalConfiguration.createGlobalConfiguration(new String[] {});
141         } catch (ConfigurationException e) {
142             e.printStackTrace();
143             System.exit(1);
144         }
145         SandboxConfigDump configDump = new SandboxConfigDump();
146         int code = configDump.parse(mainArgs);
147         System.exit(code);
148     }
149 
getSandboxOptions(IConfiguration config)150     private SandboxOptions getSandboxOptions(IConfiguration config) {
151         return (SandboxOptions)
152                 config.getConfigurationObject(Configuration.SANBOX_OPTIONS_TYPE_NAME);
153     }
154 
secureDeviceAllocation(IConfiguration config)155     private void secureDeviceAllocation(IConfiguration config) {
156         for (IDeviceConfiguration deviceConfig : config.getDeviceConfig()) {
157             IDeviceSelection requirements = deviceConfig.getDeviceRequirements();
158             if (requirements.nullDeviceRequested()
159                     || requirements.tcpDeviceRequested()
160                     || requirements.gceDeviceRequested()) {
161                 // Reset serials, ensure any null/tcp/gce-device can be selected.
162                 requirements.setSerial();
163             }
164         }
165     }
166 }
167