1#!/usr/bin/python
2# Copyright 2017 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import argparse
7import logging
8import os
9import shutil
10import tempfile
11import unittest
12
13import common
14from autotest_lib.site_utils import lxc
15from autotest_lib.site_utils.lxc import unittest_logging
16
17
18options = None
19container_path = None
20
21def setUpModule():
22    """Creates a directory for running the unit tests. """
23    global container_path
24    container_path = tempfile.mkdtemp(
25            dir=lxc.DEFAULT_CONTAINER_PATH,
26            prefix='container_bucket_unittest_')
27
28
29def tearDownModule():
30    """Deletes the test directory. """
31    shutil.rmtree(container_path)
32
33
34class ContainerBucketTests(unittest.TestCase):
35    """Unit tests for the ContainerBucket class."""
36
37    def setUp(self):
38        self.tmpdir = tempfile.mkdtemp()
39        self.shared_host_path = os.path.realpath(os.path.join(self.tmpdir,
40                                                              'host'))
41
42
43    def tearDown(self):
44        shutil.rmtree(self.tmpdir)
45
46
47    def testHostDirCreationAndCleanup(self):
48        """Verifies that the host dir is properly created and cleaned up when
49        the container bucket is set up and destroyed.
50        """
51        bucket = lxc.ContainerBucket(container_path, self.shared_host_path)
52
53        # Verify the host path in the container bucket.
54        self.assertEqual(os.path.realpath(bucket.shared_host_path),
55                         self.shared_host_path)
56
57        # Set up, verify that the path is created.
58        bucket.setup_base()
59        self.assertTrue(os.path.isdir(self.shared_host_path))
60
61        # Clean up, verify that the path is removed.
62        bucket.destroy_all()
63        self.assertFalse(os.path.isdir(self.shared_host_path))
64
65
66    def testHostDirMissing(self):
67        """Verifies that a missing host dir does not cause container bucket
68        destruction to crash.
69        """
70        bucket = lxc.ContainerBucket(container_path, self.shared_host_path)
71
72        # Verify that the host path does not exist.
73        self.assertFalse(os.path.exists(self.shared_host_path))
74        # Do not call startup, just call destroy.  This should not throw.
75        bucket.destroy_all()
76
77
78class ContainerBucketSetupBaseTests(unittest.TestCase):
79    """Unit tests to verify the ContainerBucket setup_base method."""
80
81    def setUp(self):
82        self.tmpdir = tempfile.mkdtemp()
83        self.shared_host_path = os.path.realpath(os.path.join(self.tmpdir,
84                                                              'host'))
85        self.bucket = lxc.ContainerBucket(container_path,
86                                          self.shared_host_path)
87
88
89    def tearDown(self):
90        for container in self.bucket.get_all().values():
91            container.stop()
92        self.bucket.destroy_all()
93        shutil.rmtree(self.tmpdir)
94
95
96    # TODO(kenobi): Read moblab_config.ini to get the correct base version
97    # instead of hard-coding it.
98    def testSetupBase05(self):
99        """Verifies that the code for installing the rootfs location into the
100        lxc config, is working correctly.
101        """
102        # Set up the bucket, then start the base container, and verify it works.
103        self.downloadAndStart('base_05')
104
105
106    # TODO(kenobi): Read shadow_config.ini to get the correct base version
107    # instead of hard-coding it.
108    def testSetupBase09(self):
109        """Verifies that the setup_base code works with the base_09 image. """
110        self.downloadAndStart('base_09')
111
112
113    def downloadAndStart(self, name):
114        """Calls setup_base with the given base image name, then starts the
115        container and verifies that it is running.
116
117        @param name: The name of the base image to download and test with.
118        """
119        self.bucket.setup_base(name=name)
120        base_container = self.bucket.get(name)
121        base_container.start()
122        self.assertTrue(base_container.is_running())
123
124def parse_options():
125    """Parse command line inputs."""
126    parser = argparse.ArgumentParser()
127    parser.add_argument('-v', '--verbose', action='store_true',
128                        help='Print out ALL entries.')
129    args, _unused = parser.parse_known_args()
130    return args
131
132
133if __name__ == '__main__':
134    options = parse_options()
135
136    log_level=(logging.DEBUG if options.verbose else logging.INFO)
137    unittest_logging.setup(log_level)
138
139    unittest.main()
140