poky: subtree update:a616ffebdc..9052e5b32a

Adrian Bunk (1):
      bind: Whitelist CVE-2019-6470

Alexander Kanavin (13):
      python: update to 2.7.17
      tiff: update to 4.1.0
      librepo: upgrade 1.10.6 -> 1.11.0
      btrfs-tools: upgrade 5.3 -> 5.3.1
      psmisc: update to 23.3
      libxslt: update to 1.1.34
      Revert "devtool/standard.py: Not filtering devtool workspace for devtool finish"
      mpg123: upgrade 1.25.12 -> 1.25.13
      vala: upgrade 0.46.3 -> 0.46.4
      sysstat: upstream version check is working again
      cairo: the component is dual licensed
      selftest: check that 'devtool upgrade' correctly drops backported patches
      runqemu: add options that enable virgl with the SDL frontend

Alistair Francis (1):
      mesa: Upgrade to 19.2.4

Anuj Mittal (7):
      boost: fix build for x32
      rng-tools: upgrade 6.7 -> 6.8
      harfbuzz: upgrade 2.6.1 -> 2.6.4
      libsolv: upgrade 0.7.6 -> 0.7.8
      sqlite3: upgrade 3.30.0 -> 3.30.1
      stress-ng: upgrade 0.10.08 -> 0.10.10
      glib-2.0: upgrade 2.62.1 -> 2.62.2

Armin Kuster (9):
      oeqa/manual/bsp-hw: remove rpm -ivh test
      oeqa/runtime/boot: add reboot test
      oeqa/manual/bsp-hw: remove reboot test
      oeqa/manual/bsp-hw: move storage tests to runtime
      oeqa/manual/bsp-hw: remove usb and SDmicro tests
      manual/bsd-hw: remove bash tests
      oeqa/manual/compliance-test: remove crashme tests
      oeqa/manual/compliance-test: move crashme to runtime
      /oeqa/manual/compliance-test: remove obsolete test

Chee Yang Lee (2):
      wic: rm with -r flag support
      selftest/wic: test wic rm with -r flag

Denys Dmytriyenko (1):
      distro_features_check: expand with MACHINE_FEATURES and COMBINED_FEATURES, rename

Kai Kang (1):
      systemd: remove ${PN}-xorg-xinitrc

Khem Raj (1):
      webkitgtk: Remove clang specific option

Paul Barker (1):
      cdrtools-native: Don't set uid/gid during install

Paul Eggleton (1):
      devtool: fix devtool upgrade with reproducible_builds class

Richard Purdie (10):
      oeqa/devtool: Avoid unbound variable errors
      recipetool/create: Fix to work with reproducible_builds
      opkg: Add upstream fixes for empty packages
      opkg-utils: Fix silent empty/broken opkg package creation
      core-image-full-cmdline: Add less
      bitbake: fetch2/clearcase: Fix warnings from python 3.8
      bitbake: runqueue: Fix hash equivalence duplicate tasks running
      sanity: Add check for tar older than 1.28
      oeqa/selftest/sstatetests: Ensure we don't use hashequiv for sstatesigs tests
      package_ipk: Remove pointless comment to trigger rebuild

Ross Burton (8):
      cve-update-db-native: don't hardcode the database name
      cve-update-db-native: add an index on the CVE ID column
      cve-update-db-native: clean up proxy handling
      cve-check: rewrite look to fix false negatives
      cve-check: neaten get_cve_info
      cve-check: fetch CVE data once at a time instead of in a single call
      bitbake: tests: add test for the hashing functions
      bitbake: utils: also use mmap for SHA256 and SHA1, for performance

Yi Zhao (1):
      bitbake: contrib/vim/indent/bitbake.vim: move it to correct directory

Change-Id: I526155f21145180c764252a2ae5bfba33def10ff
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/poky/meta/lib/oeqa/manual/bsp-hw.json b/poky/meta/lib/oeqa/manual/bsp-hw.json
index 18cec22..5c5b9b5 100644
--- a/poky/meta/lib/oeqa/manual/bsp-hw.json
+++ b/poky/meta/lib/oeqa/manual/bsp-hw.json
@@ -1,32 +1,6 @@
 [
     {
         "test": {
-            "@alias": "bsps-hw.bsps-hw.rpm_-__install_dependency_package",
-            "author": [
-                {
-                    "email": "alexandru.c.georgescu@intel.com",
-                    "name": "alexandru.c.georgescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "Get a not previously installed RPM package or build one on local machine, which should have run-time dependency.For example, \"mc\" (Midnight Commander, which is a visual file manager) should depend on \"ncurses-terminfo\".   \n\n$ bitbake mc  \n\n\n",
-                    "expected_results": ""
-                },
-                "2": {
-                    "action": "Copy the package into a system folder (for example /home/root/rpm_packages).  \n\n\n",
-                    "expected_results": ""
-                },
-                "3": {
-                    "action": "Run \"rpm -ivh package_name\" and check the output, for example \"rpm -ivh mc.rpm*\" should report the dependency on \"ncurses-terminfo\".\n\n\n\n",
-                    "expected_results": "3 . rpm command should report message when some RPM installation depends on other packages."
-                }
-            },
-            "summary": "rpm_-__install_dependency_package"
-        }
-    },
-    {
-        "test": {
             "@alias": "bsps-hw.bsps-hw.boot_and_install_from_USB",
             "author": [
                 {
@@ -173,28 +147,6 @@
     },
     {
         "test": {
-            "@alias": "bsps-hw.bsps-hw.reboot_system",
-            "author": [
-                {
-                    "email": "alexandru.c.georgescu@intel.com",
-                    "name": "alexandru.c.georgescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "boot system",
-                    "expected_results": ""
-                },
-                "2": {
-                    "action": "launch terminal and run \"reboot\"",
-                    "expected_results": "System can reboot successfully . "
-                }
-            },
-            "summary": "reboot_system"
-        }
-    },
-    {
-        "test": {
             "@alias": "bsps-hw.bsps-hw.switch_among_multi_applications_and_desktop",
             "author": [
                 {
@@ -225,114 +177,6 @@
     },
     {
         "test": {
-            "@alias": "bsps-hw.bsps-hw.USB_-_mount",
-            "author": [
-                {
-                    "email": "alexandru.c.georgescu@intel.com",
-                    "name": "alexandru.c.georgescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "Boot system \n\n",
-                    "expected_results": ""
-                },
-                "2": {
-                    "action": "Plug USB stick, it should be mount in  /run/media/sd(x) If X-window system does not start and show USB device, then use the terminal to mount it, following the next steps: \na. Locate the usb stick (usually it is on /dev/sdb) \nb. Create a directory with \"mkdir stick\"  (so you will have such a path as: /home/root/stick). \nc. Run the command  \"mount  /dev/sdb  /home/root/stick\" to mount  USB device on it. \n\n",
-                    "expected_results": "USB device should be mounted in  /run/media/sd(x)  \nor in  /home/root/stick  \n\n"
-                },
-                "3": {
-                    "action": "Then you can access USB stick (/home/root/stick) via Terminal or GUI  and try various commands and actions like \"cp\", \"mv\", \"touch\" and \"rm\".  Type \"dmesg\" command and check for recent mounted devices.",
-                    "expected_results": "Basic commands work properly. The system sends a notification in \"dmesg\" command, showing that the USB stick is accessible and the device is mounted ."
-                }
-            },
-            "summary": "USB_-_mount"
-        }
-    },
-    {
-        "test": {
-            "@alias": "bsps-hw.bsps-hw.USB_-_read_files",
-            "author": [
-                {
-                    "email": "alexandru.c.georgescu@intel.com",
-                    "name": "alexandru.c.georgescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "boot system",
-                    "expected_results": "view/copy successfully"
-                },
-                "2": {
-                    "action": "plug usb stick",
-                    "expected_results": ""
-                },
-                "3": {
-                    "action": "view files in usb by file browser",
-                    "expected_results": ""
-                },
-                "4": {
-                    "action": "copy some files from usb to local hardware",
-                    "expected_results": ""
-                }
-            },
-            "summary": "USB_-_read_files"
-        }
-    },
-    {
-        "test": {
-            "@alias": "bsps-hw.bsps-hw.USB_-_umount",
-            "author": [
-                {
-                    "email": "alexandru.c.georgescu@intel.com",
-                    "name": "alexandru.c.georgescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "boot system",
-                    "expected_results": "usb directory in file browser automatically missed"
-                },
-                "2": {
-                    "action": "plug usb stick",
-                    "expected_results": ""
-                },
-                "3": {
-                    "action": "view files in usb by file browser \n4.unplug usb",
-                    "expected_results": ""
-                }
-            },
-            "summary": "USB_-_umount"
-        }
-    },
-    {
-        "test": {
-            "@alias": "bsps-hw.bsps-hw.USB_-_write_files",
-            "author": [
-                {
-                    "email": "alexandru.c.georgescu@intel.com",
-                    "name": "alexandru.c.georgescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "boot system",
-                    "expected_results": "create/copy successfully"
-                },
-                "2": {
-                    "action": "plug usb stick",
-                    "expected_results": ""
-                },
-                "3": {
-                    "action": "create files in usb \n4.copy some files from local hardware to usb",
-                    "expected_results": ""
-                }
-            },
-            "summary": "USB_-_write_files"
-        }
-    },
-    {
-        "test": {
             "@alias": "bsps-hw.bsps-hw.ethernet_static_ip_set_in_connman",
             "author": [
                 {
@@ -613,136 +457,6 @@
     },
     {
         "test": {
-            "@alias": "bsps-hw.bsps-hw.check_bash_in_image",
-            "author": [
-                {
-                    "email": "alexandru.c.georgescu@intel.com",
-                    "name": "alexandru.c.georgescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "After system is up, check if bash command exists with command \"which bash\"",
-                    "expected_results": "bash command should exist in image giving something as below  \"/bin/bash\""
-                }
-            },
-            "summary": "check_bash_in_image"
-        }
-    },
-    {
-        "test": {
-            "@alias": "bsps-hw.bsps-hw.MicroSD_-__mount",
-            "author": [
-                {
-                    "email": "alexandru.c.georgescu@intel.com",
-                    "name": "alexandru.c.georgescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "boot system",
-                    "expected_results": "system notify that MicroSDis accessible"
-                },
-                "2": {
-                    "action": "plug MicroSD card",
-                    "expected_results": ""
-                }
-            },
-            "summary": "MicroSD_-__mount"
-        }
-    },
-    {
-        "test": {
-            "@alias": "bsps-hw.bsps-hw.MicroSD_-__read_files",
-            "author": [
-                {
-                    "email": "alexandru.c.georgescu@intel.com",
-                    "name": "alexandru.c.georgescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "boot system",
-                    "expected_results": "view/copy successfully"
-                },
-                "2": {
-                    "action": "plug MicroSD card",
-                    "expected_results": ""
-                },
-                "3": {
-                    "action": "view files inMicroSD by file browser",
-                    "expected_results": ""
-                },
-                "4": {
-                    "action": "copy some files fromMicroSD to local hardware",
-                    "expected_results": ""
-                }
-            },
-            "summary": "MicroSD_-__read_files"
-        }
-    },
-    {
-        "test": {
-            "@alias": "bsps-hw.bsps-hw.MicroSD_-__umount",
-            "author": [
-                {
-                    "email": "alexandru.c.georgescu@intel.com",
-                    "name": "alexandru.c.georgescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "boot system",
-                    "expected_results": "MicroSD in file browser automatically missed . "
-                },
-                "2": {
-                    "action": "plug MicroSD card",
-                    "expected_results": ""
-                },
-                "3": {
-                    "action": "view files in MicroSDby file browser",
-                    "expected_results": ""
-                },
-                "4": {
-                    "action": "unplug MicroSD",
-                    "expected_results": ""
-                }				
-            },
-            "summary": "MicroSD_-__umount"
-        }
-    },
-    {
-        "test": {
-            "@alias": "bsps-hw.bsps-hw.MicroSD_-__write_files",
-            "author": [
-                {
-                    "email": "alexandru.c.georgescu@intel.com",
-                    "name": "alexandru.c.georgescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "boot system",
-                    "expected_results": "create/copy successfully"
-                },
-                "2": {
-                    "action": "plug MicroSD card",
-                    "expected_results": ""
-                },
-                "3": {
-                    "action": "create files in MicroSD",
-                    "expected_results": ""
-                },
-                "4": {
-                    "action": "copy some files from local hardware to MicroSD",
-                    "expected_results": ""
-                }
-            },
-            "summary": "MicroSD_-__write_files"
-        }
-    },
-    {
-        "test": {
             "@alias": "bsps-hw.bsps-hw.video_-_libva_check_(ogg_video_play)",
             "author": [
                 {
@@ -1283,4 +997,4 @@
             "summary": "Boot_from_JFFS2_image"
         }
     }
-]
\ No newline at end of file
+]
diff --git a/poky/meta/lib/oeqa/manual/compliance-test.json b/poky/meta/lib/oeqa/manual/compliance-test.json
deleted file mode 100644
index 367a416..0000000
--- a/poky/meta/lib/oeqa/manual/compliance-test.json
+++ /dev/null
@@ -1,76 +0,0 @@
-[
-    {
-        "test": {
-            "@alias": "compliance-test.compliance-test.stress_test_-_Genericx86-64",
-            "author": [
-                {
-                    "email": "corneliux.stoicescu@intel.com",
-                    "name": "corneliux.stoicescu@intel.com"
-                }
-            ],
-            "execution": {
-                "1": {
-                    "action": "Bootup with core-image-sato-sdk image",
-                    "expected_results": ""
-                },
-                "2": {
-                    "action": "Execute the crashme test with below command  \n\n./opt/ltp/runltp f  crashme",
-                    "expected_results": "The stress testing should not make the target crash. Check CPU usage and basic functionality of the system after the tests are over. "
-                }
-            },
-            "summary": "stress_test_-_Genericx86-64"
-        }
-    },
-     {
-    "test": {
-      "@alias": "compliance-test.compliance-test.stress_test_-_- crashme_-_-Beaglebone",
-      "author": [
-        {
-          "email": "corneliux.stoicescu@intel.com",
-          "name": "corneliux.stoicescu@intel.com"
-        }
-      ],
-      "execution": {
-        "1": {
-          "action": " Get crashme from http://people.delphiforums.com/gjc/crashme.html",
-          "expected_results": ""
-        },
-        "2": {
-          "action": "Follow the setup steps on above URL, build crashme in target",
-          "expected_results": ""
-        },
-        "3": {
-          "action": " Run crashme for 24 hours",
-          "expected_results": "Target should not crash with the program."
-        }
-      },
-      "summary": "stress_test_-_crashme_-Beaglebone"
-    }
-  },
-  {
-    "test": {
-      "@alias": "compliance-test.compliance-test.stress_test_-_ltp_-Beaglebone",
-      "author": [
-        {
-          "email": "corneliux.stoicescu@intel.com",
-          "name": "corneliux.stoicescu@intel.com"
-        }
-      ],
-      "execution": {
-        "1": {
-          "action": "Build LTP with toolchain or in sdk image",
-          "expected_results": ""
-        },
-        "2": {
-          "action": "Copy LTP folder into target, for example, /opt/ltp. Modify script,  testscripts/ltpstress.sh, set Iostat=1, NO_NETWORK=1",
-          "expected_results": ""
-        },
-        "3": {
-          "action": "cd testscripts/ && ./ltpstress.sh",
-          "expected_results": "This stress case will run for 24 hours Check the result\ntarget should not crash with the program "
-        }
-      },
-      "summary": "stress_test_-_-ltp_-Beaglebone"
-    }
-  }
-]
diff --git a/poky/meta/lib/oeqa/runtime/cases/boot.py b/poky/meta/lib/oeqa/runtime/cases/boot.py
new file mode 100644
index 0000000..2142f40
--- /dev/null
+++ b/poky/meta/lib/oeqa/runtime/cases/boot.py
@@ -0,0 +1,33 @@
+#
+# SPDX-License-Identifier: MIT
+#
+
+from subprocess import Popen, PIPE
+import time
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.oetimeout import OETimeout
+from oeqa.core.decorator.data import skipIfQemu
+
+class BootTest(OERuntimeTestCase):
+
+    @OETimeout(120)
+    @skipIfQemu('qemuall', 'Test only runs on real hardware')
+    @OETestDepends(['ssh.SSHTest.test_ssh'])
+    def test_reboot(self):
+        output = ''
+        count = 0
+        (status, output) = self.target.run('reboot -h')
+        while count < 5:
+            time.sleep(5)
+            cmd = 'ping -c 1 %s' % self.target.ip
+            proc = Popen(cmd, shell=True, stdout=PIPE)
+            output += proc.communicate()[0].decode('utf-8')
+            if proc.poll() == 0:
+                count += 1
+            else:
+                count = 0
+        msg = ('Expected 5 consecutive, got %d.\n'
+               'ping output is:\n%s' % (count,output))
+        self.assertEqual(count, 5, msg = msg)
diff --git a/poky/meta/lib/oeqa/runtime/cases/ltp_stress.py b/poky/meta/lib/oeqa/runtime/cases/ltp_stress.py
new file mode 100644
index 0000000..2445ffb
--- /dev/null
+++ b/poky/meta/lib/oeqa/runtime/cases/ltp_stress.py
@@ -0,0 +1,98 @@
+# LTP Stress runtime
+#
+# Copyright (c) 2019 MontaVista Software, LLC
+#
+# SPDX-License-Identifier: MIT
+#
+
+import time
+import datetime
+import pprint
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+from oeqa.core.decorator.data import skipIfQemu
+from oeqa.utils.logparser import LtpParser
+
+class LtpStressBase(OERuntimeTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        cls.ltp_startup()
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.ltp_finishup()
+
+    @classmethod
+    def ltp_startup(cls):
+        cls.sections = {}
+        cls.failmsg = ""
+        test_log_dir = os.path.join(cls.td.get('WORKDIR', ''), 'testimage')
+        timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
+
+        cls.ltptest_log_dir_link = os.path.join(test_log_dir, 'ltpstress_log')
+        cls.ltptest_log_dir = '%s.%s' % (cls.ltptest_log_dir_link, timestamp)
+        os.makedirs(cls.ltptest_log_dir)
+
+        cls.tc.target.run("mkdir -p /opt/ltp/results")
+
+        if not hasattr(cls.tc, "extraresults"):
+            cls.tc.extraresults = {}
+        cls.extras = cls.tc.extraresults
+        cls.extras['ltpstressresult.rawlogs'] = {'log': ""}
+
+ 
+    @classmethod
+    def ltp_finishup(cls):
+        cls.extras['ltpstressresult.sections'] =  cls.sections
+
+        # update symlink to ltp_log
+        if os.path.exists(cls.ltptest_log_dir_link):
+            os.remove(cls.ltptest_log_dir_link)
+
+        os.symlink(os.path.basename(cls.ltptest_log_dir), cls.ltptest_log_dir_link)
+
+        if cls.failmsg:
+            cls.fail(cls.failmsg)
+
+class LtpStressTest(LtpStressBase):
+
+    def runltp(self, stress_group):
+            cmd = '/opt/ltp/runltp -f %s -p -q 2>@1 | tee /opt/ltp/results/%s' % (stress_group, stress_group)
+            starttime = time.time()
+            (status, output) = self.target.run(cmd)
+            endtime = time.time()
+            with open(os.path.join(self.ltptest_log_dir, "%s" % stress_group), 'w') as f:
+                f.write(output)
+
+            self.extras['ltpstressresult.rawlogs']['log'] = self.extras['ltpstressresult.rawlogs']['log'] + output
+
+            parser = LtpParser()
+            results, sections  = parser.parse(os.path.join(self.ltptest_log_dir, "%s" % stress_group))
+
+            runtime = int(endtime-starttime)
+            sections['duration'] = runtime
+            self.sections[stress_group] =  sections
+ 
+            failed_tests = {}
+            for test in results:
+                result = results[test]
+                testname = ("ltpstressresult." + stress_group + "." + test)
+                self.extras[testname] = {'status': result}
+                if result == 'FAILED':
+                    failed_tests[stress_group] = test 
+
+            if failed_tests:
+                self.failmsg = self.failmsg + "Failed ptests:\n%s" % pprint.pformat(failed_tests)
+
+    # LTP stress runtime tests
+    #
+    @skipIfQemu('qemuall', 'Test only runs on real hardware')
+
+    @OETestDepends(['ssh.SSHTest.test_ssh'])
+    @OEHasPackage(["ltp"])
+    def test_ltp_stress(self):
+        self.tc.target.run("sed -i -r 's/^fork12.*//' /opt/ltp/runtest/crashme")
+        self.runltp('crashme')
diff --git a/poky/meta/lib/oeqa/runtime/cases/storage.py b/poky/meta/lib/oeqa/runtime/cases/storage.py
new file mode 100644
index 0000000..166d26b
--- /dev/null
+++ b/poky/meta/lib/oeqa/runtime/cases/storage.py
@@ -0,0 +1,149 @@
+#
+# SPDX-License-Identifier: MIT
+#
+
+import re
+import time
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.data import skipIfQemu
+
+class StorageBase(OERuntimeTestCase):
+    def storage_mount(cls, tmo=1):
+
+        (status, output) = cls.target.run('mkdir -p %s' % cls.mount_point)
+        (status, output) = cls.target.run('mount %s %s' % (cls.device, cls.mount_point))
+        msg = ('Mount failed: %s.' % status)
+        cls.assertFalse(output, msg = msg)
+        time.sleep(tmo)
+        (status, output) = cls.target.run('cat /proc/mounts')
+        match = re.search('%s' % cls.device, output)
+        if match:
+            msg = ('Device %s not mounted.' % cls.device)
+            cls.assertTrue(match, msg = msg)
+
+        (status, output) = cls.target.run('mkdir -p %s' % cls.test_dir)
+
+        (status, output) = cls.target.run('rm -f %s/*' % cls.test_dir)
+        msg = ('Failed to cleanup files @ %s/*' % cls.test_dir)
+        cls.assertFalse(output, msg = msg)
+
+
+    def storage_basic(cls):
+        # create file on device
+        (status, output) = cls.target.run('touch %s/%s' % (cls.test_dir, cls.test_file))
+        msg = ('File %s not created on %s' % (cls.test_file, cls.device))
+        cls.assertFalse(status, msg = msg)
+        # move file
+        (status, output) = cls.target.run('mv %s/%s %s/%s1' %  
+                (cls.test_dir, cls.test_file, cls.test_dir, cls.test_file))
+        msg = ('File %s not moved to %s' % (cls.test_file, cls.device))
+        cls.assertFalse(status, msg = msg)
+        # remove file
+        (status, output) = cls.target.run('rm %s/%s1' % (cls.test_dir, cls.test_file))
+        msg = ('File %s not removed on %s' % (cls.test_file, cls.device))
+        cls.assertFalse(status, msg = msg)
+
+    def storage_read(cls):
+        # check if message is in file
+        (status, output) = cls.target.run('cat  %s/%s' % 
+                (cls.test_dir, cls.test_file))
+
+        match = re.search('%s' % cls.test_msg, output)
+        msg = ('Test message %s not in file %s.' % (cls.test_msg, cls.test_file))
+        cls.assertEqual(status, 0,  msg = msg)
+
+    def storage_write(cls):
+        # create test message in file on device
+        (status, output) = cls.target.run('echo "%s" >  %s/%s' % 
+                (cls.test_msg, cls.test_dir, cls.test_file))
+        msg = ('File %s not create test message on %s' % (cls.test_file, cls.device))
+        cls.assertEqual(status, 0,  msg = msg)
+
+    def storage_umount(cls, tmo=1):
+        time.sleep(tmo)
+        (status, output) = cls.target.run('umount %s' % cls.mount_point)
+
+        if status == 32:
+            # already unmounted, should it fail?
+            return
+        else:
+            msg = ('Device not unmount %s' % cls.mount_point)
+            cls.assertEqual(status, 0,  msg = msg)
+
+        (status, output) = cls.target.run('cat /proc/mounts')
+        match = re.search('%s' % cls.device, output)
+        if match:
+            msg = ('Device %s still mounted.' % cls.device)
+            cls.assertTrue(match, msg = msg)
+
+
+class UsbTest(StorageBase):
+    '''
+        This is to mimic the usb test previously done in manual bsp-hw.json
+    '''
+    @classmethod
+    def setUpClass(self):
+        self.test_msg = "Hello World - USB"
+        self.mount_point = "/media/usb"
+        self.device = "/dev/sda1"
+        self.test_file = "usb.tst"
+        self.test_dir = os.path.join(self.mount_point, "oeqa")
+
+    @skipIfQemu('qemuall', 'Test only runs on real hardware')
+    @OETestDepends(['ssh.SSHTest.test_ssh'])
+    def test_usb_mount(self):
+        self.storage_umount(2)
+        self.storage_mount(5)
+
+    @skipIfQemu('qemuall', 'Test only runs on real hardware')
+    @OETestDepends(['storage.UsbTest.test_usb_mount'])
+    def test_usb_basic_operations(self):
+        self.storage_basic()
+
+    @skipIfQemu('qemuall', 'Test only runs on real hardware')
+    @OETestDepends(['storage.UsbTest.test_usb_basic_operations'])
+    def test_usb_basic_rw(self):
+        self.storage_write()
+        self.storage_read()
+
+    @skipIfQemu('qemuall', 'Test only runs on real hardware')
+    @OETestDepends(['storage.UsbTest.test_usb_mount'])
+    def test_usb_umount(self):
+        self.storage_umount(2)
+
+
+class MMCTest(StorageBase):
+    '''
+        This is to mimic the usb test previously done in manual bsp-hw.json
+    '''
+    @classmethod
+    def setUpClass(self):
+        self.test_msg = "Hello World - MMC"
+        self.mount_point = "/media/mmc"
+        self.device = "/dev/mmcblk1p1"
+        self.test_file = "mmc.tst"
+        self.test_dir = os.path.join(self.mount_point, "oeqa")
+
+    @skipIfQemu('qemuall', 'Test only runs on real hardware')
+    @OETestDepends(['ssh.SSHTest.test_ssh'])
+    def test_mmc_mount(self):
+        self.storage_umount(2)
+        self.storage_mount()
+
+    @skipIfQemu('qemuall', 'Test only runs on real hardware')
+    @OETestDepends(['storage.MMCTest.test_mmc_mount'])
+    def test_mmc_basic_operations(self):
+        self.storage_basic()
+
+    @skipIfQemu('qemuall', 'Test only runs on real hardware')
+    @OETestDepends(['storage.MMCTest.test_mmc_basic_operations'])
+    def test_mmc_basic_rw(self):
+        self.storage_write()
+        self.storage_read()
+
+    @skipIfQemu('qemuall', 'Test only runs on real hardware')
+    @OETestDepends(['storage.MMCTest.test_mmc_mount'])
+    def test_mmc_umount(self):
+        self.storage_umount(2)
diff --git a/poky/meta/lib/oeqa/selftest/cases/devtool.py b/poky/meta/lib/oeqa/selftest/cases/devtool.py
index 3a25da2..57e6662 100644
--- a/poky/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/poky/meta/lib/oeqa/selftest/cases/devtool.py
@@ -137,6 +137,7 @@
         with open(recipefile, 'r') as f:
             invar = None
             invalue = None
+            inherits = set()
             for line in f:
                 var = None
                 if invar:
@@ -158,7 +159,7 @@
                         invar = var
                         continue
                 elif line.startswith('inherit '):
-                    inherits = line.split()[1:]
+                    inherits.update(line.split()[1:])
 
                 if var and var in checkvars:
                     needvalue = checkvars.pop(var)
@@ -1496,11 +1497,13 @@
         recipedir = os.path.dirname(oldrecipefile)
         olddir = os.path.join(recipedir, recipe + '-' + oldversion)
         patchfn = '0001-Add-a-note-line-to-the-quick-reference.patch'
+        backportedpatchfn = 'backported.patch'
         self.assertExists(os.path.join(olddir, patchfn), 'Original patch file does not exist')
-        return recipe, oldrecipefile, recipedir, olddir, newversion, patchfn
+        self.assertExists(os.path.join(olddir, backportedpatchfn), 'Backported patch file does not exist')
+        return recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn
 
     def test_devtool_finish_upgrade_origlayer(self):
-        recipe, oldrecipefile, recipedir, olddir, newversion, patchfn = self._setup_test_devtool_finish_upgrade()
+        recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn = self._setup_test_devtool_finish_upgrade()
         # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
         self.assertIn('/meta-selftest/', recipedir)
         # Try finish to the original layer
@@ -1511,14 +1514,23 @@
         self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
         self.assertNotExists(oldrecipefile, 'Old recipe file should have been deleted but wasn\'t')
         self.assertNotExists(os.path.join(olddir, patchfn), 'Old patch file should have been deleted but wasn\'t')
+        self.assertNotExists(os.path.join(olddir, backportedpatchfn), 'Old backported patch file should have been deleted but wasn\'t')
         newrecipefile = os.path.join(recipedir, '%s_%s.bb' % (recipe, newversion))
         newdir = os.path.join(recipedir, recipe + '-' + newversion)
         self.assertExists(newrecipefile, 'New recipe file should have been copied into existing layer but wasn\'t')
         self.assertExists(os.path.join(newdir, patchfn), 'Patch file should have been copied into new directory but wasn\'t')
+        self.assertNotExists(os.path.join(newdir, backportedpatchfn), 'Backported patch file should not have been copied into new directory but was')
         self.assertExists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch'), 'New patch file should have been created but wasn\'t')
+        with open(newrecipefile, 'r') as f:
+            newcontent = f.read()
+        self.assertNotIn(backportedpatchfn, newcontent, "Backported patch should have been removed from the recipe but wasn't")
+        self.assertIn(patchfn, newcontent, "Old patch should have not been removed from the recipe but was")
+        self.assertIn("0002-Add-a-comment-to-the-code.patch", newcontent, "New patch should have been added to the recipe but wasn't")
+        self.assertIn("http://www.ivarch.com/programs/sources/pv-${PV}.tar.gz", newcontent, "New recipe no longer has upstream source in SRC_URI")
+
 
     def test_devtool_finish_upgrade_otherlayer(self):
-        recipe, oldrecipefile, recipedir, olddir, newversion, patchfn = self._setup_test_devtool_finish_upgrade()
+        recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn = self._setup_test_devtool_finish_upgrade()
         # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
         self.assertIn('/meta-selftest/', recipedir)
         # Try finish to a different layer - should create a bbappend
@@ -1534,10 +1546,18 @@
         self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
         self.assertExists(oldrecipefile, 'Old recipe file should not have been deleted')
         self.assertExists(os.path.join(olddir, patchfn), 'Old patch file should not have been deleted')
+        self.assertExists(os.path.join(olddir, backportedpatchfn), 'Old backported patch file should not have been deleted')
         newdir = os.path.join(newrecipedir, recipe + '-' + newversion)
         self.assertExists(newrecipefile, 'New recipe file should have been copied into existing layer but wasn\'t')
         self.assertExists(os.path.join(newdir, patchfn), 'Patch file should have been copied into new directory but wasn\'t')
+        self.assertNotExists(os.path.join(newdir, backportedpatchfn), 'Backported patch file should not have been copied into new directory but was')
         self.assertExists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch'), 'New patch file should have been created but wasn\'t')
+        with open(newrecipefile, 'r') as f:
+            newcontent = f.read()
+        self.assertNotIn(backportedpatchfn, newcontent, "Backported patch should have been removed from the recipe but wasn't")
+        self.assertIn(patchfn, newcontent, "Old patch should have not been removed from the recipe but was")
+        self.assertIn("0002-Add-a-comment-to-the-code.patch", newcontent, "New patch should have been added to the recipe but wasn't")
+        self.assertIn("http://www.ivarch.com/programs/sources/pv-${PV}.tar.gz", newcontent, "New recipe no longer has upstream source in SRC_URI")
 
     def _setup_test_devtool_finish_modify(self):
         # Check preconditions
diff --git a/poky/meta/lib/oeqa/selftest/cases/sstatetests.py b/poky/meta/lib/oeqa/selftest/cases/sstatetests.py
index 2867cb7..6757a0e 100644
--- a/poky/meta/lib/oeqa/selftest/cases/sstatetests.py
+++ b/poky/meta/lib/oeqa/selftest/cases/sstatetests.py
@@ -255,6 +255,7 @@
 BUILD_OS = "linux"
 SDKMACHINE = "x86_64"
 PACKAGE_CLASSES = "package_rpm package_ipk package_deb"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """)
         self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
         bitbake("core-image-sato -S none")
@@ -266,6 +267,7 @@
 BUILD_OS = "linux"
 SDKMACHINE = "i686"
 PACKAGE_CLASSES = "package_rpm package_ipk package_deb"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """)
         self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
         bitbake("core-image-sato -S none")
@@ -298,6 +300,7 @@
 TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
 TCLIBCAPPEND = \"\"
 NATIVELSBSTRING = \"DistroA\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """)
         self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
         bitbake("core-image-sato -S none")
@@ -305,6 +308,7 @@
 TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
 TCLIBCAPPEND = \"\"
 NATIVELSBSTRING = \"DistroB\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """)
         self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
         bitbake("core-image-sato -S none")
@@ -332,11 +336,13 @@
 TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
 TCLIBCAPPEND = \"\"
 MACHINE = \"qemux86-64\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """
         configB = """
 TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
 TCLIBCAPPEND = \"\"
 MACHINE = \"qemuarm\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """
         self.sstate_allarch_samesigs(configA, configB)
 
@@ -352,6 +358,7 @@
 require conf/multilib.conf
 MULTILIBS = \"multilib:lib32\"
 DEFAULTTUNE_virtclass-multilib-lib32 = \"x86\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """
         configB = """
 TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
@@ -359,6 +366,7 @@
 MACHINE = \"qemuarm\"
 require conf/multilib.conf
 MULTILIBS = \"\"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """
         self.sstate_allarch_samesigs(configA, configB)
 
@@ -404,6 +412,7 @@
 require conf/multilib.conf
 MULTILIBS = "multilib:lib32"
 DEFAULTTUNE_virtclass-multilib-lib32 = "x86"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """)
         self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
         bitbake("world meta-toolchain -S none")
@@ -414,6 +423,7 @@
 require conf/multilib.conf
 MULTILIBS = "multilib:lib32"
 DEFAULTTUNE_virtclass-multilib-lib32 = "x86"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """)
         self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
         bitbake("world meta-toolchain -S none")
@@ -452,6 +462,7 @@
 DATE = "20161111"
 INHERIT_remove = "buildstats-summary buildhistory uninative"
 http_proxy = ""
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """)
         self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
         self.track_for_cleanup(self.topdir + "/download1")
@@ -468,6 +479,7 @@
 INHERIT_remove = "uninative"
 INHERIT += "buildstats-summary buildhistory"
 http_proxy = "http://example.com/"
+BB_SIGNATURE_HANDLER = "OEBasicHash"
 """)
         self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
         self.track_for_cleanup(self.topdir + "/download2")
diff --git a/poky/meta/lib/oeqa/selftest/cases/wic.py b/poky/meta/lib/oeqa/selftest/cases/wic.py
index ea75300..0c03b4b 100644
--- a/poky/meta/lib/oeqa/selftest/cases/wic.py
+++ b/poky/meta/lib/oeqa/selftest/cases/wic.py
@@ -1025,3 +1025,10 @@
         # check if it's removed
         result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
         self.assertTrue('fstab' not in [line.split()[-1] for line in result.output.split('\n') if line])
+
+        # remove non-empty directory
+        runCmd("wic rm -r %s:2/etc/ -n %s" % (images[0], sysroot))
+
+        # check if it's removed
+        result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
+        self.assertTrue('etc' not in [line.split()[-1] for line in result.output.split('\n') if line])