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