gtk: Add a PropertyList model

Along with Property, PropertyValue, and PropertyFilter objects that are used
togther to show specific properties to the user when placed in a
Gtk.ColumnView.

Signed-off-by: Anna Schumaker <anna@nowheycreamery.com>
This commit is contained in:
Anna Schumaker 2023-08-15 14:36:38 -04:00
parent 4838889c56
commit 59cb699bd9
4 changed files with 218 additions and 0 deletions

View File

@ -101,6 +101,103 @@ class TestXunitList(unittest.TestCase):
self.assertListEqual(self.xulist.get_xunits(), ["xunit-1", "xunit-2"])
class TestPropertyValue(unittest.TestCase):
"""Tests a single Xunit Property instance."""
def test_xunit_property(self):
"""Test creating an xunit property instance."""
property = xfstestsdb.gtk.model.PropertyValue(name="my xunit name",
key="key", value="123")
self.assertIsInstance(property, xfstestsdb.gtk.model.XunitCell)
self.assertEqual(property.name, "my xunit name")
self.assertEqual(property.key, "key")
self.assertEqual(property.value, "123")
self.assertEqual(str(property), "key = 123")
class TestProperty(unittest.TestCase):
"""Tests our Property GObject."""
def setUp(self):
"""Set up common variables."""
self.property = xfstestsdb.gtk.model.Property(name="property")
def test_init(self):
"""Check that the Property is set up properly."""
self.assertIsInstance(self.property, xfstestsdb.gtk.model.XunitRow)
self.assertEqual(self.property.name, "property")
def test_xunits(self):
"""Test adding xunits to a Property."""
self.assertIsNone(self.property["xunit-1"])
self.property.add_xunit("xunit-1", "PLATFORM", "linux-123")
property = self.property["xunit-1"]
self.assertIsInstance(property, xfstestsdb.gtk.model.PropertyValue)
self.assertEqual(property.name, "xunit-1")
self.assertEqual(property.key, "PLATFORM")
self.assertEqual(property.value, "linux-123")
self.assertTrue(self.property.all_same_value())
self.property.add_xunit("xunit-2", "PLATFORM", "linux-123")
property = self.property["xunit-2"]
self.assertIsInstance(property, xfstestsdb.gtk.model.PropertyValue)
self.assertEqual(property.name, "xunit-2")
self.assertEqual(property.key, "PLATFORM")
self.assertEqual(property.value, "linux-123")
self.assertTrue(self.property.all_same_value())
self.property.add_xunit("xunit-3", "PLATFORM", "linux-456")
self.assertFalse(self.property.all_same_value())
class TestPropertyList(unittest.TestCase):
"""Tests our PropertyList GObject."""
def setUp(self):
"""Set up common variables."""
self.xfstestsdb = xfstestsdb.Command()
with unittest.mock.patch("sys.stdout"):
self.xfstestsdb.run(["new", "/dev/vda1"])
self.xfstestsdb.run(["xunit", "read", "--name", "xunit-1",
"1", str(tests.xunit.XUNIT_1)])
self.xfstestsdb.run(["xunit", "read", "--name", "xunit-2",
"1", str(tests.xunit.XUNIT_2)])
self.prlist = xfstestsdb.gtk.model.PropertyList(self.xfstestsdb.sql, 1)
def test_init(self):
"""Test that the PropertyList was set up properly."""
self.assertIsInstance(self.prlist, xfstestsdb.gtk.model.XunitList)
self.assertEqual(self.prlist.runid, 1)
self.assertEqual(self.prlist.n_items, 15)
class TestPropertyFilter(unittest.TestCase):
"""Tests our Gtk.Filter customized for filtering Properties."""
def setUp(self):
"""Set up common variables."""
self.filter = xfstestsdb.gtk.model.PropertyFilter()
def test_init(self):
"""Test that the TestCaseFilter is set up properly."""
self.assertIsInstance(self.filter, Gtk.Filter)
self.assertEqual(self.filter.get_strictness(), Gtk.FilterMatch.SOME)
def test_match(self):
"""Test matching Properties with the Filter."""
property = xfstestsdb.gtk.model.Property("name")
self.assertTrue(self.filter.match(property))
for prop in ["CPUS", "HOST_OPTIONS", "MEM_KB", "LOAD_FACTOR",
"NUMA_NODES", "OVL_LOWER", "OVL_UPPER", "OVL_WORK",
"PLATFORM", "SECTION", "SWAP_KB", "TIME_FACTOR"]:
with self.subTest(property=prop):
property.name = prop
self.assertFalse(self.filter.match(property))
class TestTestResult(unittest.TestCase):
"""Tests a single TestCase Xunit instance."""

View File

@ -3,3 +3,4 @@
import pathlib
XUNIT_1 = pathlib.Path(__file__).parent / "test-1.xunit"
XUNIT_2 = pathlib.Path(__file__).parent / "test-2.xunit"

68
tests/xunit/test-2.xunit Normal file
View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuite
xmlns="https://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git https://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git/tree/doc/xunit.xsd"
name="xfstests"
failures="1" skipped="3" tests="10" time="43"
hostname="myhost"
start_timestamp="2023-01-31T14:14:14-05:00"
timestamp="2023-01-31T14:14:55-05:00"
report_timestamp="2023-01-31T14:14:57-05:00"
>
<properties>
<property name="SECTION" value="-no-sections-"/>
<property name="FSTYP" value="myfs"/>
<property name="PLATFORM" value="Linux/x86_64 myhost 6.1.8-arch1"/>
<property name="MOUNT_OPTIONS" value="-o mountopt1,mountopt3"/>
<property name="HOST_OPTIONS" value="local.config"/>
<property name="CHECK_OPTIONS" value="-r -R xunit -g quick"/>
<property name="TIME_FACTOR" value="1"/>
<property name="LOAD_FACTOR" value="1"/>
<property name="TEST_DIR" value="/mnt/test2"/>
<property name="TEST_DEV" value="/dev/vdb3"/>
<property name="SCRATCH_DEV" value="/dev/vdb4"/>
<property name="SCRATCH_MNT" value="/mnt/scratch2"/>
<property name="OVL_UPPER" value="ovl-upper"/>
<property name="OVL_LOWER" value="ovl-lower"/>
<property name="OVL_WORK" value="ovl-work"/>
</properties>
<testcase classname="xfstests.global" name="test/01" time="1">
</testcase>
<testcase classname="xfstests.global" name="test/02" time="0">
<skipped message="skipped on /dev/vdb1" />
</testcase>
<testcase classname="xfstests.global" name="test/03" time="0">
<skipped message="skipped on /mnt/test too" />
</testcase>
<testcase classname="xfstests.global" name="test/04" time="4">
</testcase>
<testcase classname="xfstests.global" name="test/05" time="5">
</testcase>
<testcase classname="xfstests.global" name="test/06" time="6">
</testcase>
<testcase classname="xfstests.global" name="test/07" time="0">
<skipped message="fstype &quot;myfs&quot; gets skipped" />
</testcase>
<testcase classname="xfstests.global" name="test/08" time="8">
</testcase>
<testcase classname="xfstests.global" name="test/09" time="9">
<failure message="- output mismatch (see somefile)" type="TestFail" />
<system-out>
<![CDATA[
there was a problem with &apos;/dev/vdb2&apos;
]]>
</system-out>
<system-err>
<![CDATA[
--- test/09.out 2023-01-31 14:14:14.141414 -1414
+++ results/some/sub/dir/test/09.out.bad 2023-02-02 16:16:16.161616 -1616
there was a problem with &apos;/mnt/scratch&apos;
]]>
</system-err>
</testcase>
<testcase classname="xfstests.global" name="test/10" time="10">
</testcase>
</testsuite>

View File

@ -93,6 +93,58 @@ class XunitList(GObject.GObject, Gio.ListModel):
return sorted(self.__xunits)
class PropertyValue(XunitCell):
"""A single Property for a specific Xunit."""
key = GObject.Property(type=str)
value = GObject.Property(type=str)
def __str__(self) -> str:
"""Get a string representation of this Property."""
return f"{self.key} = {self.value}"
class Property(XunitRow):
"""Collects one property across multiple xunits."""
def do_make_xunit(self, name: str, key: str, value: str) -> PropertyValue:
"""Add a PropertyValue to the Property."""
return PropertyValue(name=name, key=key, value=value)
def all_same_value(self) -> bool:
"""Check if all the xunits have the same value."""
return len(self.get_results()) == 1
class PropertyList(XunitList):
"""A list of Properties for a specific Xfstests Run."""
def do_query(self, sql: sqlite.Connection) -> sqlite3.Cursor:
"""Query the database for properties."""
return sql("""SELECT xunit, key, value FROM xunit_properties_view
WHERE runid=?""", self.runid)
def do_parse(self, rows: dict[Property], row: sqlite3.Cursor) -> None:
"""Parse the data in the row and add it to the rows dict."""
property = rows.setdefault(row["key"], Property(row["key"]))
property.add_xunit(row["xunit"], row["key"], row["value"])
class PropertyFilter(Gtk.Filter):
"""A filter for Properties."""
def do_get_strictness(self) -> Gtk.FilterMatch:
"""Get the strictness of the filter."""
return Gtk.FilterMatch.SOME
def do_match(self, property: Property) -> bool:
"""Check if a property matches the filter."""
hidden = {"CPUS", "HOST_OPTIONS", "LOAD_FACTOR", "MEM_KB",
"NUMA_NODES", "OVL_LOWER", "OVL_UPPER", "OVL_WORK",
"PLATFORM", "SECTION", "SWAP_KB", "TIME_FACTOR"}
return property.name not in hidden
class TestResult(XunitCell):
"""The results for a single TestCase with a specific Xunit."""