xfstestsdb/tests/test_gc.py
Anna Schumaker 14654dcf23 gc: Create the xfstestsdb gc command
This command is used to garbage collect the xfstestsdb sqlite database.
It removes xfstests runs that have no added xunits, and runs older than
180 days that have not been tagged.

Implements: #16 (`xfstestsdb gc`)
Signed-off-by: Anna Schumaker <anna@nowheycreamery.com>
2023-07-26 11:26:09 -04:00

124 lines
5.2 KiB
Python

# Copyright 2023 (c) Anna Schumaker.
"""Tests the `xfstestsdb gc` command."""
import datetime
import io
import unittest
import unittest.mock
import xfstestsdb.xunit.gc
import tests.xunit
class TestGC(unittest.TestCase):
"""Tests the `xfstestsdb xunit gc` command."""
def setUp(self):
"""Set up common variables."""
self.xfstestsdb = xfstestsdb.Command()
self.xunit = self.xfstestsdb.commands["xunit"]
self.gc = self.xunit.commands["gc"]
def setup_runs(self, mock_stdout: io.StringIO):
"""Set up runs in the database and clear stdout."""
self.xfstestsdb.run(["new", "/dev/vda1"])
self.xfstestsdb.run(["new", "/dev/vda1"])
self.xfstestsdb.run(["new", "/dev/vda1"])
self.xfstestsdb.run(["xunit", "read", "1", str(tests.xunit.XUNIT_1)])
self.xfstestsdb.run(["xunit", "read", "3", str(tests.xunit.XUNIT_1)])
self.xfstestsdb.sql("DELETE FROM testcases WHERE xunitid=2")
mock_stdout.seek(0)
mock_stdout.truncate(0)
def test_init(self):
"""Check that the gc command was set up properly."""
self.assertIsInstance(self.gc, xfstestsdb.commands.Command)
self.assertIsInstance(self.gc, xfstestsdb.xunit.gc.Command)
self.assertEqual(self.xunit.subparser.choices["gc"],
self.gc.parser)
@unittest.mock.patch("sys.stdout", new_callable=io.StringIO)
def test_gc_empty(self, mock_stdout: io.StringIO):
"""Test garbage collecting an empty database."""
cur = self.xfstestsdb.sql("SELECT runid FROM xfstests_gc_runs")
self.assertListEqual([row['runid'] for row in cur.fetchall()], [])
self.xfstestsdb.run(["gc"])
self.assertEqual(mock_stdout.getvalue(), "")
@unittest.mock.patch("sys.stdout", new_callable=io.StringIO)
def test_gc_no_testcases(self, mock_stdout: io.StringIO):
"""Test garbage collecting runs with no testcases."""
self.setup_runs(mock_stdout)
cur = self.xfstestsdb.sql("SELECT runid FROM xfstests_gc_runs")
self.assertListEqual([row['runid'] for row in cur.fetchall()], [2, 3])
self.xfstestsdb.run(["gc"])
self.assertRegex(mock_stdout.getvalue(),
"run #2 has been deleted\nrun #3 has been deleted")
cur = self.xfstestsdb.sql("SELECT runid FROM xfstests_runs")
self.assertListEqual([row['runid'] for row in cur.fetchall()], [1])
@unittest.mock.patch("sys.stdout", new_callable=io.StringIO)
def test_gc_expired(self, mock_stdout: io.StringIO):
"""Test garbage collecting old runs."""
self.setup_runs(mock_stdout)
self.xfstestsdb.run(["xunit", "read", "2", str(tests.xunit.XUNIT_1)])
utcnow = datetime.datetime.utcnow()
expired = utcnow - datetime.timedelta(days=180, seconds=1)
self.xfstestsdb.sql("""UPDATE xfstests_runs SET timestamp=?
WHERE runid=1""", expired)
not_expired = utcnow - datetime.timedelta(days=180, seconds=-1)
self.xfstestsdb.sql("""UPDATE xfstests_runs SET timestamp=?
WHERE runid=2""", not_expired)
cur = self.xfstestsdb.sql("SELECT runid FROM xfstests_gc_runs")
self.assertListEqual([row['runid'] for row in cur.fetchall()], [1, 3])
self.xfstestsdb.run(["gc"])
self.assertRegex(mock_stdout.getvalue(),
"run #1 has been deleted\nrun #3 has been deleted")
cur = self.xfstestsdb.sql("SELECT runid FROM xfstests_runs")
self.assertListEqual([row['runid'] for row in cur.fetchall()], [2])
@unittest.mock.patch("sys.stdout", new_callable=io.StringIO)
def test_gc_expired_tagged(self, mock_stdout: io.StringIO):
"""Test that we don't garbage collect expired runs that are tagged."""
self.setup_runs(mock_stdout)
self.xfstestsdb.run(["xunit", "read", "2", str(tests.xunit.XUNIT_1)])
self.xfstestsdb.run(["tag", "1", "my-tag"])
self.xfstestsdb.run(["tag", "3", "my-tag"])
utcnow = datetime.datetime.utcnow()
expired = utcnow - datetime.timedelta(days=181)
self.xfstestsdb.sql("UPDATE xfstests_runs SET timestamp=?", expired)
cur = self.xfstestsdb.sql("SELECT runid FROM xfstests_gc_runs")
self.assertListEqual([row['runid'] for row in cur.fetchall()], [2, 3])
self.xfstestsdb.run(["gc"])
self.assertRegex(mock_stdout.getvalue(),
"run #2 has been deleted\nrun #3 has been deleted")
cur = self.xfstestsdb.sql("SELECT runid FROM xfstests_runs")
self.assertListEqual([row['runid'] for row in cur.fetchall()], [1])
@unittest.mock.patch("sys.stdout", new_callable=io.StringIO)
def test_gc_dry_run(self, mock_stdout: io.StringIO):
"""Test garbage collecting with the --dry-run option."""
self.setup_runs(mock_stdout)
self.xfstestsdb.run(["gc", "--dry-run"])
self.assertRegex(mock_stdout.getvalue(),
"run #2 would be deleted\nrun #3 would be deleted")
cur = self.xfstestsdb.sql("SELECT runid FROM xfstests_runs")
self.assertListEqual([row['runid'] for row in cur.fetchall()],
[1, 2, 3])