/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.tradefed.sandbox;

import com.android.annotations.VisibleForTesting;
import com.android.tradefed.command.CommandOptions;
import com.android.tradefed.config.Configuration;
import com.android.tradefed.config.ConfigurationException;
import com.android.tradefed.config.ConfigurationFactory;
import com.android.tradefed.config.GlobalConfiguration;
import com.android.tradefed.config.IConfiguration;
import com.android.tradefed.config.IConfigurationFactory;
import com.android.tradefed.config.IGlobalConfiguration;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.invoker.InvocationContext;
import com.android.tradefed.invoker.proto.InvocationContext.Context;
import com.android.tradefed.log.ITestLogger;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.FileInputStreamSource;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.proto.StreamProtoReceiver;
import com.android.tradefed.result.proto.StreamProtoResultReporter;
import com.android.tradefed.sandbox.SandboxConfigDump.DumpCmd;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.IRunUtil;
import com.android.tradefed.util.PrettyPrintDelimiter;
import com.android.tradefed.util.QuotationAwareTokenizer;
import com.android.tradefed.util.RunUtil;
import com.android.tradefed.util.StreamUtil;
import com.android.tradefed.util.SubprocessTestResultsParser;
import com.android.tradefed.util.SystemUtil;
import com.android.tradefed.util.keystore.IKeyStoreClient;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Sandbox container that can run a Trade Federation invocation. TODO: Allow Options to be passed to
 * the sandbox.
 */
public class TradefedSandbox implements ISandbox {

    private static final String SANDBOX_PREFIX = "sandbox-";

    private File mStdoutFile = null;
    private File mStderrFile = null;
    private OutputStream mStdout = null;
    private FileOutputStream mStderr = null;
    private File mHeapDump = null;

    private File mSandboxTmpFolder = null;
    private File mRootFolder = null;
    private File mGlobalConfig = null;
    private File mSerializedContext = null;
    private File mSerializedConfiguration = null;

    private SubprocessTestResultsParser mEventParser = null;
    private StreamProtoReceiver mProtoReceiver = null;

    private IRunUtil mRunUtil;
    private boolean mCollectStdout = true;

    @Override
    public CommandResult run(IConfiguration config, ITestLogger logger) throws Throwable {
        List<String> mCmdArgs = new ArrayList<>();
        mCmdArgs.add(SystemUtil.getRunningJavaBinaryPath().getAbsolutePath());
        mCmdArgs.add(String.format("-Djava.io.tmpdir=%s", mSandboxTmpFolder.getAbsolutePath()));
        mCmdArgs.add(String.format("-DTF_JAR_DIR=%s", mRootFolder.getAbsolutePath()));
        // Setup heap dump collection
        try {
            mHeapDump = FileUtil.createTempDir("heap-dump");
            mCmdArgs.add("-XX:+HeapDumpOnOutOfMemoryError");
            mCmdArgs.add(String.format("-XX:HeapDumpPath=%s", mHeapDump.getAbsolutePath()));
        } catch (IOException e) {
            CLog.e(e);
        }
        mCmdArgs.addAll(getSandboxOptions(config).getJavaOptions());
        mCmdArgs.add("-cp");
        mCmdArgs.add(createClasspath(mRootFolder));
        mCmdArgs.add(TradefedSandboxRunner.class.getCanonicalName());
        mCmdArgs.add(mSerializedContext.getAbsolutePath());
        mCmdArgs.add(mSerializedConfiguration.getAbsolutePath());
        if (mProtoReceiver != null) {
            mCmdArgs.add("--" + StreamProtoResultReporter.PROTO_REPORT_PORT_OPTION);
            mCmdArgs.add(Integer.toString(mProtoReceiver.getSocketServerPort()));
        } else {
            mCmdArgs.add("--subprocess-report-port");
            mCmdArgs.add(Integer.toString(mEventParser.getSocketServerPort()));
        }
        if (config.getCommandOptions().shouldUseSandboxTestMode()) {
            // In test mode, re-add the --use-sandbox to trigger a sandbox run again in the process
            mCmdArgs.add("--" + CommandOptions.USE_SANDBOX);
        }

        long timeout = config.getCommandOptions().getInvocationTimeout();
        // Allow interruption, subprocess should handle signals itself
        mRunUtil.allowInterrupt(true);
        CommandResult result =
                mRunUtil.runTimedCmd(timeout, mStdout, mStderr, mCmdArgs.toArray(new String[0]));
        // Log stdout and stderr
        if (mStdoutFile != null) {
            try (InputStreamSource sourceStdOut = new FileInputStreamSource(mStdoutFile)) {
                logger.testLog("sandbox-stdout", LogDataType.TEXT, sourceStdOut);
            }
        }
        try (InputStreamSource sourceStdErr = new FileInputStreamSource(mStderrFile)) {
            logger.testLog("sandbox-stderr", LogDataType.TEXT, sourceStdErr);
        }
        // Collect heap dump if any
        logAndCleanHeapDump(mHeapDump, logger);

        boolean failedStatus = false;
        String stderrText;
        try {
            stderrText = FileUtil.readStringFromFile(mStderrFile);
        } catch (IOException e) {
            stderrText = "Could not read the stderr output from process.";
        }
        if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
            failedStatus = true;
            result.setStderr(stderrText);
        }
        // Log the configuration used to run
        try (InputStreamSource configFile = new FileInputStreamSource(mSerializedConfiguration)) {
            logger.testLog("sandbox-config", LogDataType.XML, configFile);
        }
        try (InputStreamSource contextFile = new FileInputStreamSource(mSerializedContext)) {
            logger.testLog("sandbox-context", LogDataType.PB, contextFile);
        }

        boolean joinResult = false;
        long waitTime = getSandboxOptions(config).getWaitForEventsTimeout();
        if (mProtoReceiver != null) {
            joinResult = mProtoReceiver.joinReceiver(waitTime);
        } else {
            joinResult = mEventParser.joinReceiver(waitTime);
        }

        if (!joinResult) {
            if (!failedStatus) {
                result.setStatus(CommandStatus.EXCEPTION);
            }
            result.setStderr(
                    String.format("Event receiver thread did not complete.:\n%s", stderrText));
        }
        if (mProtoReceiver != null) {
            mProtoReceiver.completeModuleEvents();
        }
        PrettyPrintDelimiter.printStageDelimiter(
                String.format(
                        "Execution of the tests occurred in the sandbox, you can find its logs "
                                + "under the name pattern '%s*'",
                        SANDBOX_PREFIX));

        return result;
    }

    @Override
    public Exception prepareEnvironment(
            IInvocationContext context, IConfiguration config, ITestInvocationListener listener) {
        // Check for local sharding, avoid redirecting several stdout (from each shards) to the
        // sandbox stdout as it creates a lot of I/O to the same output.
        if (config.getCommandOptions().getShardCount() != null
                && config.getCommandOptions().getShardIndex() == null) {
            mCollectStdout = false;
        }
        // Create our temp directories.
        try {
            if (mCollectStdout) {
                mStdoutFile = FileUtil.createTempFile("stdout_subprocess_", ".log");
                mStdout = new FileOutputStream(mStdoutFile);
            } else {
                mStdout =
                        new OutputStream() {
                            @Override
                            public void write(int b) throws IOException {
                                // Ignore stdout
                            }
                        };
            }

            mStderrFile = FileUtil.createTempFile("stderr_subprocess_", ".log");
            mStderr = new FileOutputStream(mStderrFile);

            mSandboxTmpFolder = FileUtil.createTempDir("tradefed-container");
        } catch (IOException e) {
            return e;
        }
        // Unset the current global environment
        mRunUtil = createRunUtil();
        mRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE);
        mRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE);
        // TODO: add handling of setting and creating the subprocess global configuration
        if (getSandboxOptions(config).shouldEnableDebugThread()) {
            mRunUtil.setEnvVariable(TradefedSandboxRunner.DEBUG_THREAD_KEY, "true");
        }
        for (Entry<String, String> envEntry :
                getSandboxOptions(config).getEnvVariables().entrySet()) {
            mRunUtil.setEnvVariable(envEntry.getKey(), envEntry.getValue());
        }

        try {
            mRootFolder =
                    getTradefedSandboxEnvironment(
                            context,
                            config,
                            QuotationAwareTokenizer.tokenizeLine(
                                    config.getCommandLine(),
                                    /** no logging */
                                    false));
        } catch (ConfigurationException e) {
            return e;
        }

        PrettyPrintDelimiter.printStageDelimiter("Sandbox Configuration Preparation");
        // Prepare the configuration
        Exception res = prepareConfiguration(context, config, listener);
        if (res != null) {
            return res;
        }
        // Prepare the context
        try {
            mSerializedContext = prepareContext(context, config);
        } catch (IOException e) {
            return e;
        }

        return null;
    }

    @Override
    public void tearDown() {
        StreamUtil.close(mEventParser);
        StreamUtil.close(mProtoReceiver);
        StreamUtil.close(mStdout);
        StreamUtil.close(mStderr);
        FileUtil.deleteFile(mStdoutFile);
        FileUtil.deleteFile(mStderrFile);
        FileUtil.recursiveDelete(mSandboxTmpFolder);
        FileUtil.deleteFile(mSerializedContext);
        FileUtil.deleteFile(mSerializedConfiguration);
        FileUtil.deleteFile(mGlobalConfig);
    }

    @Override
    public File getTradefedSandboxEnvironment(
            IInvocationContext context, IConfiguration nonVersionedConfig, String[] args)
            throws ConfigurationException {
        SandboxOptions options = getSandboxOptions(nonVersionedConfig);
        // Check that we have no args conflicts.
        if (options.getSandboxTfDirectory() != null && options.getSandboxBuildId() != null) {
            throw new ConfigurationException(
                    String.format(
                            "Sandbox options %s and %s cannot be set at the same time",
                            SandboxOptions.TF_LOCATION, SandboxOptions.SANDBOX_BUILD_ID));
        }

        if (options.getSandboxTfDirectory() != null) {
            return options.getSandboxTfDirectory();
        }
        String tfDir = System.getProperty("TF_JAR_DIR");
        if (tfDir == null || tfDir.isEmpty()) {
            throw new ConfigurationException(
                    "Could not read TF_JAR_DIR to get current Tradefed instance.");
        }
        return new File(tfDir);
    }

    /**
     * Create a classpath based on the environment and the working directory returned by {@link
     * #getTradefedSandboxEnvironment(IInvocationContext, IConfiguration, String[])}.
     *
     * @param workingDir the current working directory for the sandbox.
     * @return The classpath to be use.
     */
    @Override
    public String createClasspath(File workingDir) throws ConfigurationException {
        // Get the classpath property.
        String classpathStr = System.getProperty("java.class.path");
        if (classpathStr == null) {
            throw new ConfigurationException(
                    "Could not find the classpath property: java.class.path");
        }
        return classpathStr;
    }

    /**
     * Prepare the {@link IConfiguration} that will be passed to the subprocess and will drive the
     * container execution.
     *
     * @param context The current {@link IInvocationContext}.
     * @param config the {@link IConfiguration} to be prepared.
     * @param listener The current invocation {@link ITestInvocationListener}.
     * @return an Exception if anything went wrong, null otherwise.
     */
    protected Exception prepareConfiguration(
            IInvocationContext context, IConfiguration config, ITestInvocationListener listener) {
        try {
            // TODO: switch reporting of parent and subprocess to proto
            String commandLine = config.getCommandLine();
            if (getSandboxOptions(config).shouldUseProtoReporter()) {
                mProtoReceiver =
                        new StreamProtoReceiver(listener, context, false, false, SANDBOX_PREFIX);
                // Force the child to the same mode as the parent.
                commandLine = commandLine + " --" + SandboxOptions.USE_PROTO_REPORTER;
            } else {
                mEventParser = new SubprocessTestResultsParser(listener, true, context);
                commandLine = commandLine + " --no-" + SandboxOptions.USE_PROTO_REPORTER;
            }
            String[] args =
                    QuotationAwareTokenizer.tokenizeLine(commandLine, /* No Logging */ false);
            mGlobalConfig = dumpGlobalConfig(config, new HashSet<>());
            try (InputStreamSource source = new FileInputStreamSource(mGlobalConfig)) {
                listener.testLog("sandbox-global-config", LogDataType.XML, source);
            }
            DumpCmd mode = DumpCmd.RUN_CONFIG;
            if (config.getCommandOptions().shouldUseSandboxTestMode()) {
                mode = DumpCmd.TEST_MODE;
            }

            try {
                mSerializedConfiguration =
                        SandboxConfigUtil.dumpConfigForVersion(
                                createClasspath(mRootFolder), mRunUtil, args, mode, mGlobalConfig);
            } catch (SandboxConfigurationException e) {
                // TODO: Improve our detection of that scenario
                CLog.e(e);
                CLog.e("%s", args[0]);
                if (e.getMessage().contains(String.format("Can not find local config %s", args[0]))
                        || e.getMessage()
                                .contains(
                                        String.format(
                                                "Could not find configuration '%s'", args[0]))) {
                    CLog.w(
                            "Child version doesn't contains '%s'. Attempting to backfill missing parent configuration.",
                            args[0]);
                    File parentConfig = handleChildMissingConfig(args);
                    if (parentConfig != null) {
                        try (InputStreamSource source = new FileInputStreamSource(parentConfig)) {
                            listener.testLog("sandbox-parent-config", LogDataType.XML, source);
                        }
                        try {
                            mSerializedConfiguration =
                                    SandboxConfigUtil.dumpConfigForVersion(
                                            createClasspath(mRootFolder),
                                            mRunUtil,
                                            new String[] {parentConfig.getAbsolutePath()},
                                            mode,
                                            mGlobalConfig);
                        } finally {
                            FileUtil.deleteFile(parentConfig);
                        }
                        return null;
                    }
                }
                throw e;
            }
            // Turn off some of the invocation level options that would be duplicated in the
            // child sandbox subprocess.
            config.getCommandOptions().setBugreportOnInvocationEnded(false);
            config.getCommandOptions().setBugreportzOnInvocationEnded(false);
        } catch (IOException | ConfigurationException e) {
            StreamUtil.close(mEventParser);
            StreamUtil.close(mProtoReceiver);
            return e;
        }
        return null;
    }

    @VisibleForTesting
    IRunUtil createRunUtil() {
        return new RunUtil();
    }

    /**
     * Prepare and serialize the {@link IInvocationContext}.
     *
     * @param context the {@link IInvocationContext} to be prepared.
     * @param config The {@link IConfiguration} of the sandbox.
     * @return the serialized {@link IInvocationContext}.
     * @throws IOException
     */
    protected File prepareContext(IInvocationContext context, IConfiguration config)
            throws IOException {
        // In test mode we need to keep the context unlocked for the next layer.
        if (config.getCommandOptions().shouldUseSandboxTestMode()) {
            try {
                Method unlock = InvocationContext.class.getDeclaredMethod("unlock");
                unlock.setAccessible(true);
                unlock.invoke(context);
                unlock.setAccessible(false);
            } catch (NoSuchMethodException
                    | SecurityException
                    | IllegalAccessException
                    | IllegalArgumentException
                    | InvocationTargetException e) {
                throw new IOException("Couldn't unlock the context.", e);
            }
        }
        File protoFile =
                FileUtil.createTempFile(
                        "context-proto", "." + LogDataType.PB.getFileExt(), mSandboxTmpFolder);
        Context contextProto = context.toProto();
        contextProto.writeDelimitedTo(new FileOutputStream(protoFile));
        return protoFile;
    }

    /** Dump the global configuration filtered from some objects. */
    protected File dumpGlobalConfig(IConfiguration config, Set<String> exclusionPatterns)
            throws IOException, ConfigurationException {
        SandboxOptions options = getSandboxOptions(config);
        if (options.getChildGlobalConfig() != null) {
            IConfigurationFactory factory = ConfigurationFactory.getInstance();
            IGlobalConfiguration globalConfig =
                    factory.createGlobalConfigurationFromArgs(
                            new String[] {options.getChildGlobalConfig()}, new ArrayList<>());
            CLog.d(
                    "Using %s directly as global config without filtering",
                    options.getChildGlobalConfig());
            return globalConfig.cloneConfigWithFilter();
        }
        return SandboxConfigUtil.dumpFilteredGlobalConfig(exclusionPatterns);
    }

    /** {@inheritDoc} */
    @Override
    public IConfiguration createThinLauncherConfig(
            String[] args, IKeyStoreClient keyStoreClient, IRunUtil runUtil, File globalConfig) {
        // Default thin launcher cannot do anything, since this sandbox uses the same version as
        // the parent version.
        return null;
    }

    private SandboxOptions getSandboxOptions(IConfiguration config) {
        return (SandboxOptions)
                config.getConfigurationObject(Configuration.SANBOX_OPTIONS_TYPE_NAME);
    }

    private File handleChildMissingConfig(String[] args) {
        IConfiguration parentConfig = null;
        File tmpParentConfig = null;
        PrintWriter pw = null;
        try {
            tmpParentConfig = FileUtil.createTempFile("parent-config", ".xml", mSandboxTmpFolder);
            pw = new PrintWriter(tmpParentConfig);
            parentConfig = ConfigurationFactory.getInstance().createConfigurationFromArgs(args);
            // Do not print deprecated options to avoid compatibility issues, and do not print
            // unchanged options.
            parentConfig.dumpXml(pw, new ArrayList<>(), false, false);
            return tmpParentConfig;
        } catch (ConfigurationException | IOException e) {
            CLog.e("Parent doesn't understand the command either:");
            CLog.e(e);
            FileUtil.deleteFile(tmpParentConfig);
            return null;
        } finally {
            StreamUtil.close(pw);
        }
    }

    private void logAndCleanHeapDump(File heapDumpDir, ITestLogger logger) {
        try {
            if (heapDumpDir != null && heapDumpDir.listFiles().length != 0) {
                for (File f : heapDumpDir.listFiles()) {
                    FileInputStreamSource fileInput = new FileInputStreamSource(f);
                    logger.testLog(f.getName(), LogDataType.HPROF, fileInput);
                    StreamUtil.cancel(fileInput);
                }
            }
        } finally {
            FileUtil.recursiveDelete(heapDumpDir);
        }
    }
}
