1from oeqa.selftest.case import OESelftestTestCase
2from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu
3from oeqa.utils.sshcontrol import SSHControl
4from oeqa.core.decorator.oeid import OETestID
5import os
6import re
7import tempfile
8import shutil
9
10class TestExport(OESelftestTestCase):
11
12    @classmethod
13    def tearDownClass(cls):
14        runCmd("rm -rf /tmp/sdk")
15        super(TestExport, cls).tearDownClass()
16
17    @OETestID(1499)
18    def test_testexport_basic(self):
19        """
20        Summary: Check basic testexport functionality with only ping test enabled.
21        Expected: 1. testexport directory must be created.
22                  2. runexported.py must run without any error/exception.
23                  3. ping test must succeed.
24        Product: oe-core
25        Author: Mariano Lopez <mariano.lopez@intel.com>
26        """
27
28        features = 'INHERIT += "testexport"\n'
29        # These aren't the actual IP addresses but testexport class needs something defined
30        features += 'TEST_SERVER_IP = "192.168.7.1"\n'
31        features += 'TEST_TARGET_IP = "192.168.7.1"\n'
32        features += 'TEST_SUITES = "ping"\n'
33        self.write_config(features)
34
35        # Build tesexport for core-image-minimal
36        bitbake('core-image-minimal')
37        bitbake('-c testexport core-image-minimal')
38
39        testexport_dir = get_bb_var('TEST_EXPORT_DIR', 'core-image-minimal')
40
41        # Verify if TEST_EXPORT_DIR was created
42        isdir = os.path.isdir(testexport_dir)
43        self.assertEqual(True, isdir, 'Failed to create testexport dir: %s' % testexport_dir)
44
45        with runqemu('core-image-minimal') as qemu:
46            # Attempt to run runexported.py to perform ping test
47            test_path = os.path.join(testexport_dir, "oe-test")
48            data_file = os.path.join(testexport_dir, 'data', 'testdata.json')
49            manifest = os.path.join(testexport_dir, 'data', 'manifest')
50            cmd = ("%s runtime --test-data-file %s --packages-manifest %s "
51                   "--target-ip %s --server-ip %s --quiet"
52                  % (test_path, data_file, manifest, qemu.ip, qemu.server_ip))
53            result = runCmd(cmd)
54            # Verify ping test was succesful
55            self.assertEqual(0, result.status, 'oe-test runtime returned a non 0 status')
56
57    @OETestID(1641)
58    def test_testexport_sdk(self):
59        """
60        Summary: Check sdk functionality for testexport.
61        Expected: 1. testexport directory must be created.
62                  2. SDK tarball must exists.
63                  3. Uncompressing of tarball must succeed.
64                  4. Check if the SDK directory is added to PATH.
65                  5. Run tar from the SDK directory.
66        Product: oe-core
67        Author: Mariano Lopez <mariano.lopez@intel.com>
68        """
69
70        features = 'INHERIT += "testexport"\n'
71        # These aren't the actual IP addresses but testexport class needs something defined
72        features += 'TEST_SERVER_IP = "192.168.7.1"\n'
73        features += 'TEST_TARGET_IP = "192.168.7.1"\n'
74        features += 'TEST_SUITES = "ping"\n'
75        features += 'TEST_EXPORT_SDK_ENABLED = "1"\n'
76        features += 'TEST_EXPORT_SDK_PACKAGES = "nativesdk-tar"\n'
77        self.write_config(features)
78
79        # Build tesexport for core-image-minimal
80        bitbake('core-image-minimal')
81        bitbake('-c testexport core-image-minimal')
82
83        needed_vars = ['TEST_EXPORT_DIR', 'TEST_EXPORT_SDK_DIR', 'TEST_EXPORT_SDK_NAME']
84        bb_vars = get_bb_vars(needed_vars, 'core-image-minimal')
85        testexport_dir = bb_vars['TEST_EXPORT_DIR']
86        sdk_dir = bb_vars['TEST_EXPORT_SDK_DIR']
87        sdk_name = bb_vars['TEST_EXPORT_SDK_NAME']
88
89        # Check for SDK
90        tarball_name = "%s.sh" % sdk_name
91        tarball_path = os.path.join(testexport_dir, sdk_dir, tarball_name)
92        msg = "Couldn't find SDK tarball: %s" % tarball_path
93        self.assertEqual(os.path.isfile(tarball_path), True, msg)
94
95        # Extract SDK and run tar from SDK
96        result = runCmd("%s -y -d /tmp/sdk" % tarball_path)
97        self.assertEqual(0, result.status, "Couldn't extract SDK")
98
99        env_script = result.output.split()[-1]
100        result = runCmd(". %s; which tar" % env_script, shell=True)
101        self.assertEqual(0, result.status, "Couldn't setup SDK environment")
102        is_sdk_tar = True if "/tmp/sdk" in result.output else False
103        self.assertTrue(is_sdk_tar, "Couldn't setup SDK environment")
104
105        tar_sdk = result.output
106        result = runCmd("%s --version" % tar_sdk)
107        self.assertEqual(0, result.status, "Couldn't run tar from SDK")
108
109
110class TestImage(OESelftestTestCase):
111
112    @OETestID(1644)
113    def test_testimage_install(self):
114        """
115        Summary: Check install packages functionality for testimage/testexport.
116        Expected: 1. Import tests from a directory other than meta.
117                  2. Check install/uninstall of socat.
118        Product: oe-core
119        Author: Mariano Lopez <mariano.lopez@intel.com>
120        """
121        if get_bb_var('DISTRO') == 'poky-tiny':
122            self.skipTest('core-image-full-cmdline not buildable for poky-tiny')
123
124        features = 'INHERIT += "testimage"\n'
125        features += 'TEST_SUITES = "ping ssh selftest"\n'
126        self.write_config(features)
127
128        # Build core-image-sato and testimage
129        bitbake('core-image-full-cmdline socat')
130        bitbake('-c testimage core-image-full-cmdline')
131
132    @OETestID(1883)
133    def test_testimage_dnf(self):
134        """
135        Summary: Check package feeds functionality for dnf
136        Expected: 1. Check that remote package feeds can be accessed
137        Product: oe-core
138        Author: Alexander Kanavin <alexander.kanavin@intel.com>
139        """
140        if get_bb_var('DISTRO') == 'poky-tiny':
141            self.skipTest('core-image-full-cmdline not buildable for poky-tiny')
142
143        features = 'INHERIT += "testimage"\n'
144        features += 'TEST_SUITES = "ping ssh dnf_runtime dnf.DnfBasicTest.test_dnf_help"\n'
145        # We don't yet know what the server ip and port will be - they will be patched
146        # in at the start of the on-image test
147        features += 'PACKAGE_FEED_URIS = "http://bogus_ip:bogus_port"\n'
148        features += 'EXTRA_IMAGE_FEATURES += "package-management"\n'
149        features += 'PACKAGE_CLASSES = "package_rpm"\n'
150
151        # Enable package feed signing
152        self.gpg_home = tempfile.mkdtemp(prefix="oeqa-feed-sign-")
153        signing_key_dir = os.path.join(self.testlayer_path, 'files', 'signing')
154        runCmd('gpg --batch --homedir %s --import %s' % (self.gpg_home, os.path.join(signing_key_dir, 'key.secret')))
155        features += 'INHERIT += "sign_package_feed"\n'
156        features += 'PACKAGE_FEED_GPG_NAME = "testuser"\n'
157        features += 'PACKAGE_FEED_GPG_PASSPHRASE_FILE = "%s"\n' % os.path.join(signing_key_dir, 'key.passphrase')
158        features += 'GPG_PATH = "%s"\n' % self.gpg_home
159        self.write_config(features)
160
161        # Build core-image-sato and testimage
162        bitbake('core-image-full-cmdline socat')
163        bitbake('-c testimage core-image-full-cmdline')
164
165        # remove the oeqa-feed-sign temporal directory
166        shutil.rmtree(self.gpg_home, ignore_errors=True)
167
168class Postinst(OESelftestTestCase):
169    @OETestID(1540)
170    @OETestID(1545)
171    def test_postinst_rootfs_and_boot(self):
172        """
173        Summary:        The purpose of this test case is to verify Post-installation
174                        scripts are called when rootfs is created and also test
175                        that script can be delayed to run at first boot.
176        Dependencies:   NA
177        Steps:          1. Add proper configuration to local.conf file
178                        2. Build a "core-image-minimal" image
179                        3. Verify that file created by postinst_rootfs recipe is
180                           present on rootfs dir.
181                        4. Boot the image created on qemu and verify that the file
182                           created by postinst_boot recipe is present on image.
183        Expected:       The files are successfully created during rootfs and boot
184                        time for 3 different package managers: rpm,ipk,deb and
185                        for initialization managers: sysvinit and systemd.
186
187        """
188
189        import oe.path
190
191        vars = get_bb_vars(("IMAGE_ROOTFS", "sysconfdir"), "core-image-minimal")
192        rootfs = vars["IMAGE_ROOTFS"]
193        self.assertIsNotNone(rootfs)
194        sysconfdir = vars["sysconfdir"]
195        self.assertIsNotNone(sysconfdir)
196        # Need to use oe.path here as sysconfdir starts with /
197        hosttestdir = oe.path.join(rootfs, sysconfdir, "postinst-test")
198        targettestdir = os.path.join(sysconfdir, "postinst-test")
199
200        for init_manager in ("sysvinit", "systemd"):
201            for classes in ("package_rpm", "package_deb", "package_ipk"):
202                with self.subTest(init_manager=init_manager, package_class=classes):
203                    features = 'CORE_IMAGE_EXTRA_INSTALL = "postinst-delayed-b"\n'
204                    features += 'IMAGE_FEATURES += "package-management empty-root-password"\n'
205                    features += 'PACKAGE_CLASSES = "%s"\n' % classes
206                    if init_manager == "systemd":
207                        features += 'DISTRO_FEATURES_append = " systemd"\n'
208                        features += 'VIRTUAL-RUNTIME_init_manager = "systemd"\n'
209                        features += 'DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"\n'
210                        features += 'VIRTUAL-RUNTIME_initscripts = ""\n'
211                    self.write_config(features)
212
213                    bitbake('core-image-minimal')
214
215                    self.assertTrue(os.path.isfile(os.path.join(hosttestdir, "rootfs")),
216                                    "rootfs state file was not created")
217
218                    with runqemu('core-image-minimal') as qemu:
219                        # Make the test echo a string and search for that as
220                        # run_serial()'s status code is useless.'
221                        for filename in ("rootfs", "delayed-a", "delayed-b"):
222                            status, output = qemu.run_serial("test -f %s && echo found" % os.path.join(targettestdir, filename))
223                            self.assertEqual(output, "found", "%s was not present on boot" % filename)
224
225
226
227    def test_failing_postinst(self):
228        """
229        Summary:        The purpose of this test case is to verify that post-installation
230                        scripts that contain errors are properly reported.
231        Expected:       The scriptlet failure is properly reported.
232                        The file that is created after the error in the scriptlet is not present.
233        Product: oe-core
234        Author: Alexander Kanavin <alexander.kanavin@intel.com>
235        """
236
237        import oe.path
238
239        vars = get_bb_vars(("IMAGE_ROOTFS", "sysconfdir"), "core-image-minimal")
240        rootfs = vars["IMAGE_ROOTFS"]
241        self.assertIsNotNone(rootfs)
242        sysconfdir = vars["sysconfdir"]
243        self.assertIsNotNone(sysconfdir)
244        # Need to use oe.path here as sysconfdir starts with /
245        hosttestdir = oe.path.join(rootfs, sysconfdir, "postinst-test")
246
247        for classes in ("package_rpm", "package_deb", "package_ipk"):
248            with self.subTest(package_class=classes):
249                features = 'CORE_IMAGE_EXTRA_INSTALL = "postinst-rootfs-failing"\n'
250                features += 'PACKAGE_CLASSES = "%s"\n' % classes
251                self.write_config(features)
252                bb_result = bitbake('core-image-minimal')
253                self.assertGreaterEqual(bb_result.output.find("Intentionally failing postinstall scriptlets of ['postinst-rootfs-failing'] to defer them to first boot is deprecated."), 0,
254                    "Warning about a failed scriptlet not found in bitbake output: %s" %(bb_result.output))
255
256                self.assertTrue(os.path.isfile(os.path.join(hosttestdir, "rootfs-before-failure")),
257                                    "rootfs-before-failure file was not created")
258                self.assertFalse(os.path.isfile(os.path.join(hosttestdir, "rootfs-after-failure")),
259                                    "rootfs-after-failure file was created")
260
261