#!/usr/bin/env python2
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import collections
import json
import os
import tempfile
import unittest
from contextlib import contextmanager

import common
from autotest_lib.client.bin import utils
from autotest_lib.site_utils.lxc import config as lxc_config
from autotest_lib.site_utils.lxc import utils as lxc_utils

class DeployConfigTest(unittest.TestCase):
    """Test DeployConfigManager.
    """

    def testValidate(self):
        """Test ssp_deploy_config.json can be validated.
        """
        global_deploy_config_file = os.path.join(
                common.autotest_dir, lxc_config.SSP_DEPLOY_CONFIG_FILE)
        with open(global_deploy_config_file) as f:
            deploy_configs = json.load(f)
        for config in deploy_configs:
            if 'append' in config:
                lxc_config.DeployConfigManager.validate(config)
            elif 'mount' in config:
                # validate_mount checks that the path exists, so we can't call
                # it from tests.
                pass
            else:
                self.fail('Non-deploy/mount config %s' % config)


    def testPreStart(self):
        """Verifies that pre-start works correctly.
        Checks that mounts are correctly created in the container.
        """
        with lxc_utils.TempDir() as tmpdir:
            config = [
                {
                    'mount': True,
                    'source': tempfile.mkdtemp(dir=tmpdir),
                    'target': '/target0',
                    'readonly': True,
                    'force_create': False
                },
                {
                    'mount': True,
                    'source': tempfile.mkdtemp(dir=tmpdir),
                    'target': '/target1',
                    'readonly': False,
                    'force_create': False
                },
            ]
            with ConfigFile(config) as test_cfg, MockContainer() as container:
                manager = lxc_config.DeployConfigManager(container, test_cfg)
                manager.deploy_pre_start()
                self.assertEqual(len(config), len(container.mounts))
                for c in config:
                    self.assertTrue(container.has_mount(c))


    def testPreStartWithCreate(self):
        """Verifies that pre-start creates mounted dirs.

        Checks that missing mount points are created when force_create is
        enabled.
        """
        with lxc_utils.TempDir() as tmpdir:
            src_dir = os.path.join(tmpdir, 'foobar')
            config = [{
                'mount': True,
                'source': src_dir,
                'target': '/target0',
                'readonly': True,
                'force_create': True
            }]
            with ConfigFile(config) as test_cfg, MockContainer() as container:
                manager = lxc_config.DeployConfigManager(container, test_cfg)
                # Pre-condition: the path doesn't exist.
                self.assertFalse(lxc_utils.path_exists(src_dir))

                # After calling deploy_pre_start, the path should exist and the
                # mount should be created in the container.
                manager.deploy_pre_start()
                self.assertTrue(lxc_utils.path_exists(src_dir))
                self.assertEqual(len(config), len(container.mounts))
                for c in config:
                    self.assertTrue(container.has_mount(c))


class _MockContainer(object):
    """A test mock for the container class.

    Don't instantiate this directly, use the MockContainer context manager
    defined below.
    """

    def __init__(self):
        self.rootfs = tempfile.mkdtemp()
        self.mounts = []
        self.MountConfig = collections.namedtuple(
                'MountConfig', ['source', 'destination', 'readonly'])


    def cleanup(self):
        """Clean up tmp dirs created by the container."""
        # DeployConfigManager uses sudo to create some directories in the
        # container, so it's necessary to use sudo to clean up.
        utils.run('sudo rm -rf %s' % self.rootfs)


    def mount_dir(self, src, dst, ro):
        """Stub implementation of mount_dir.

        Records calls for later verification.

        @param src: Mount source dir.
        @param dst: Mount destination dir.
        @param ro: Read-only flag.
        """
        self.mounts.append(self.MountConfig(src, dst, ro))


    def has_mount(self, config):
        """Verifies whether an earlier call was made to mount_dir.

        @param config: The config object to verify.

        @return True if an earlier call was made to mount_dir that matches the
                given mount configuration; False otherwise.
        """
        mount = self.MountConfig(config['source'],
                                 config['target'],
                                 config['readonly'])
        return mount in self.mounts


@contextmanager
def MockContainer():
    """Context manager for creating a _MockContainer for testing."""
    container = _MockContainer()
    try:
        yield container
    finally:
        container.cleanup()


@contextmanager
def ConfigFile(config):
    """Context manager for creating a config file.

    The given configs are translated into json and pushed into a temporary file
    that the DeployConfigManager can read.

    @param config: A list of config objects.  Each config object is a dictionary
                   which conforms to the format described in config.py.
    """
    with tempfile.NamedTemporaryFile() as tmp:
        json.dump(config, tmp)
        tmp.flush()
        yield tmp.name


if __name__ == '__main__':
    unittest.main()
