]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/commitdiff
resulttool: Fix UnboundLocalError when missing test results
authorMiroslav Cernak <miroslav.cernak@siemens.com>
Tue, 10 Mar 2026 12:57:53 +0000 (13:57 +0100)
committerRichard Purdie <richard.purdie@linuxfoundation.org>
Mon, 16 Mar 2026 16:49:05 +0000 (16:49 +0000)
The junit_tree function failed when either ptest or imagetest results
were missing from testresults.json due to uninitialized variables.
Move variable initialization outside the loop to ensure they
always have default values.

Signed-off-by: Miroslav Cernak <miroslav.cernak@siemens.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
meta/lib/oeqa/selftest/cases/resulttooltests.py
scripts/lib/resulttool/junit.py

index e933fc63906980c0530978c3af351f68fc52ff25..2b0e089e95987cd65c8a920b5b37c582fbdf09c2 100644 (file)
@@ -560,3 +560,112 @@ class ResultToolTests(OESelftestTestCase):
                 "test-logs/package-error-noresult.log": "ERROR: -bash: testerror: command not found\nERROR: Exit status is 123\n",
             },
         )
+
+    def test_junit_empty_testresults(self):
+        """Test junit_tree with empty testresults (e.g., missing testresults.json)"""
+        testresults = {}
+        tree, test_logfiles = junit_tree(testresults)
+        self._dump_junit_tree(testresults, tree, "junit_empty")
+        testsuites_node = tree.getroot()
+
+        # Should have zero counts for everything
+        self.assertEqual(testsuites_node.attrib["errors"], "0")
+        self.assertEqual(testsuites_node.attrib["failures"], "0")
+        self.assertEqual(testsuites_node.attrib["skipped"], "0")
+        self.assertEqual(testsuites_node.attrib["tests"], "0")
+        self.assertEqual(testsuites_node.attrib["time"], "0")
+
+        # Should have no testsuites
+        testsuites = testsuites_node.findall("testsuite")
+        self.assertEqual(len(testsuites), 0)
+
+        # No log files
+        self.assertDictEqual(test_logfiles, {})
+
+    def test_junit_missing_image_tests(self):
+        """Test junit_tree with only ptest results, no image tests"""
+        testresults = {
+            "a": {
+                "runtime_a-image": {
+                    "configuration": {"TEST_TYPE": "runtime", "MACHINE": "qemux86"},
+                    "result": {
+                        # Only ptest results, no image tests
+                        "ptestresult.package-test.test_example": {"status": "PASSED"},
+                        "ptestresult.sections": {
+                            "package-test": {
+                                "duration": "3",
+                                "log": "PASS: package-test.test_example\n",
+                            }
+                        },
+                    },
+                }
+            }
+        }
+        tree, test_logfiles = junit_tree(testresults)
+        self._dump_junit_tree(testresults, tree, "junit_no_image")
+        testsuites_node = tree.getroot()
+
+        # Should have 1 test total (only ptest)
+        self.assertEqual(testsuites_node.attrib["errors"], "0")
+        self.assertEqual(testsuites_node.attrib["failures"], "0")
+        self.assertEqual(testsuites_node.attrib["skipped"], "0")
+        self.assertEqual(testsuites_node.attrib["tests"], "1")
+        self.assertEqual(testsuites_node.attrib["time"], "3")
+
+        # Should have one main testsuite with 2 sub-testsuites
+        testsuites = testsuites_node.findall("testsuite")
+        self.assertEqual(len(testsuites), 1)
+        inner_testsuites = testsuites[0].findall("testsuite")
+        self.assertEqual(len(inner_testsuites), 2)
+
+        # Image testsuite should be empty
+        image_suite = testsuites_node.find(".//testsuite[@name='Image Tests']")
+        self.assertEqual(image_suite.attrib["tests"], "0")
+        self.assertEqual(image_suite.attrib["time"], "0")
+
+        # Package testsuite should have 1 test
+        package_suite = testsuites_node.find(".//testsuite[@name='Package Tests']")
+        self.assertEqual(package_suite.attrib["tests"], "1")
+        self.assertEqual(package_suite.attrib["time"], "3")
+
+    def test_junit_missing_ptests(self):
+        """Test junit_tree with only image tests, no ptest results"""
+        testresults = {
+            "a": {
+                "runtime_a-image": {
+                    "configuration": {"TEST_TYPE": "runtime", "MACHINE": "qemux86"},
+                    "result": {
+                        # Only image tests, no ptests
+                        "test.ImageTest.test_example": {
+                            "duration": 5,
+                            "status": "PASSED",
+                        },
+                    },
+                }
+            }
+        }
+        tree, test_logfiles = junit_tree(testresults)
+        self._dump_junit_tree(testresults, tree, "junit_no_ptest")
+        testsuites_node = tree.getroot()
+
+        # Should have 1 test total (only image test)
+        self.assertEqual(testsuites_node.attrib["errors"], "0")
+        self.assertEqual(testsuites_node.attrib["failures"], "0")
+        self.assertEqual(testsuites_node.attrib["skipped"], "0")
+        self.assertEqual(testsuites_node.attrib["tests"], "1")
+        self.assertEqual(testsuites_node.attrib["time"], "5")
+
+        # Should have one main testsuite with 1 sub-testsuite (only Image Tests)
+        testsuites = testsuites_node.findall("testsuite")
+        self.assertEqual(len(testsuites), 1)
+        inner_testsuites = testsuites[0].findall("testsuite")
+        self.assertEqual(len(inner_testsuites), 1)
+
+        # Image testsuite should have 1 test
+        image_suite = testsuites_node.find(".//testsuite[@name='Image Tests']")
+        self.assertEqual(image_suite.attrib["tests"], "1")
+        self.assertEqual(image_suite.attrib["time"], "5")
+
+        # Package testsuite should not exist (no ptestresult.sections)
+        package_suite = testsuites_node.find(".//testsuite[@name='Package Tests']")
+        self.assertIsNone(package_suite)
index 0f541dd80bd2e8f1c46d22a3039354e553901568..48f34363be924b30c6d6fe7842d47296c079f619 100644 (file)
@@ -91,6 +91,9 @@ def junit_tree(testresults, test_log_dir=None):
     """
     test_logfiles = {}
     testsuites_node = ET.Element("testsuites")
+
+    image_errors = image_failures = image_skipped = image_tests = image_total_time = 0
+    ptest_errors = ptest_failures = ptest_skipped = ptest_tests = ptest_total_time = 0
     total_errors = total_failures = total_skipped = total_tests = total_time = 0
 
     for _, run_name, _, results in resultutils.test_run_results(testresults):
@@ -98,7 +101,6 @@ def junit_tree(testresults, test_log_dir=None):
 
         # Handle all image tests but skip all ptests related sections
         imagetest_testsuite = ET.SubElement(test_run_testsuite, "testsuite", name="Image Tests")
-        image_errors = image_failures = image_skipped = image_tests = image_total_time = 0
 
         ptest_summarys = {}
 
@@ -141,7 +143,6 @@ def junit_tree(testresults, test_log_dir=None):
         imagetest_testsuite.set("time", str(image_total_time))
 
         # Handle all ptest related sections
-        ptest_errors = ptest_failures = ptest_skipped = ptest_tests = ptest_total_time = 0
         if "ptestresult.sections" in results:
             ptest_testsuite = ET.SubElement(test_run_testsuite, "testsuite", name="Package Tests")