• 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.tradefed.config.Configuration;
19 import com.android.tradefed.config.IConfiguration;
20 import com.android.tradefed.invoker.IInvocationContext;
21 import com.android.tradefed.log.LogUtil.CLog;
22 import com.android.tradefed.result.ITestInvocationListener;
23 import com.android.tradefed.util.CommandResult;
24 import com.android.tradefed.util.CommandStatus;
25 import com.android.tradefed.util.PrettyPrintDelimiter;
26 import com.android.tradefed.util.SerializationUtil;
27 
28 import org.json.JSONException;
29 import org.json.JSONObject;
30 
31 import java.io.File;
32 import java.io.IOException;
33 import java.util.regex.Matcher;
34 import java.util.regex.Pattern;
35 
36 /** Run the tests associated with the invocation in the sandbox. */
37 public class SandboxInvocationRunner {
38 
39     /** Do setup and run the tests */
prepareAndRun( IConfiguration config, IInvocationContext context, ITestInvocationListener listener)40     public static void prepareAndRun(
41             IConfiguration config, IInvocationContext context, ITestInvocationListener listener)
42             throws Throwable {
43         // TODO: refactor TestInvocation to be more modular in the sandbox handling
44         ISandbox sandbox =
45                 (ISandbox) config.getConfigurationObject(Configuration.SANDBOX_TYPE_NAME);
46         if (sandbox == null) {
47             throw new RuntimeException("Couldn't find the sandbox object.");
48         }
49         PrettyPrintDelimiter.printStageDelimiter("Starting Sandbox Environment Setup");
50         Exception res = sandbox.prepareEnvironment(context, config, listener);
51         if (res != null) {
52             CLog.w("Sandbox prepareEnvironment threw an Exception.");
53             sandbox.tearDown();
54             throw res;
55         }
56         PrettyPrintDelimiter.printStageDelimiter("Done with Sandbox Environment Setup");
57         try {
58             CommandResult result = sandbox.run(config, listener);
59             if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
60                 handleStderrException(result.getStderr());
61             }
62         } finally {
63             sandbox.tearDown();
64         }
65     }
66 
67     /** Attempt to extract a proper exception from stderr, if not stick to RuntimeException. */
handleStderrException(String stderr)68     private static void handleStderrException(String stderr) throws Throwable {
69         Pattern pattern =
70                 Pattern.compile(String.format(".*%s.*", TradefedSandboxRunner.EXCEPTION_KEY));
71         for (String line : stderr.split("\n")) {
72             Matcher m = pattern.matcher(line);
73             if (m.matches()) {
74                 try {
75                     JSONObject json = new JSONObject(line);
76                     String filePath = json.getString(TradefedSandboxRunner.EXCEPTION_KEY);
77                     File exception = new File(filePath);
78                     Throwable obj = (Throwable) SerializationUtil.deserialize(exception, true);
79                     throw obj;
80                 } catch (JSONException | IOException e) {
81                     // ignore
82                     CLog.w(
83                             "Could not parse the stderr as a particular exception. "
84                                     + "Using RuntimeException instead.");
85                 }
86             }
87         }
88         throw new RuntimeException(stderr);
89     }
90 }
91