From 81859bd3c3d82e59f61f39a7bb5c02ec9871ba89 Mon Sep 17 00:00:00 2001 From: Niels De Graef Date: Sun, 7 Dec 2025 10:09:15 +0100 Subject: [PATCH] Adapt vala-unit and tests to GLib 2.70 and later `GLib.TestSuite` is a special type of object, as it doesn't actually have an associated copy function or a reference/unreference function. In practice, that actually means there's no way to actually have 2 strong references to such an object, or to copy it somehow. Due to the way GObject properties in Vala work, that means you can't really use them either. Ever since vala commit 5f0a146f65, this got reflected properly in the internally maintained GLib VAPI (as people were experiencing double frees otherwise), but it was added only conditionally for GLib 2.70 or later. In practice, that means you only get vala compiler issues if you (impliclty) set `--target-glib=2.70` (or a later version). To fix this for vala-unit and our own Geary tests, this commit changes the `ValaUnit.TestCase` class to only allow "stealing" the strong reference to the `GLib.TestSuite`, rather than somehowing allowing people to hold a weak reference, and by also making it a protected field rather than a property. Since this changes the API of ValaUnit, we also bump the version. In general though, I hope people aren't using ValaUnit externally, since these types of API/ABI breaks can happen with Vala libraries. Link: https://gitlab.gnome.org/GNOME/vala/-/commit/5f0a146f65673379fc84c3cd8e6bca826ffad96f --- meson.build | 4 +- .../plugin/mail-merge/mail-merge-test.vala | 4 +- subprojects/vala-unit/meson.build | 8 +- subprojects/vala-unit/src/test-case.vala | 11 +- subprojects/vala-unit/test/test-driver.vala | 6 +- test/meson.build | 4 + test/test-client.vala | 26 ++--- test/test-engine.vala | 100 +++++++++--------- test/test-integration.vala | 10 +- test/test-js.vala | 10 +- 10 files changed, 98 insertions(+), 85 deletions(-) diff --git a/meson.build b/meson.build index 800b70f1..faf51b87 100644 --- a/meson.build +++ b/meson.build @@ -52,9 +52,9 @@ valac = meson.get_compiler('vala') # Required libraries and other dependencies # -target_glib = '2.68' +target_glib = '2.74' target_gtk = '3.24.24' -target_vala = '0.48.18' +target_vala = '0.56' target_webkit = '2.30' if not valac.version().version_compare('>=' + target_vala) diff --git a/src/client/plugin/mail-merge/mail-merge-test.vala b/src/client/plugin/mail-merge/mail-merge-test.vala index 39cc6d10..fac6435d 100644 --- a/src/client/plugin/mail-merge/mail-merge-test.vala +++ b/src/client/plugin/mail-merge/mail-merge-test.vala @@ -17,8 +17,8 @@ int main(string[] args) { } GLib.TestSuite root = GLib.TestSuite.get_root(); - root.add_suite(new MailMerge.TestReader().suite); - root.add_suite(new MailMerge.TestProcessor().suite); + root.add_suite(new MailMerge.TestReader().steal_suite()); + root.add_suite(new MailMerge.TestProcessor().steal_suite()); GLib.MainLoop loop = new GLib.MainLoop(); int ret = -1; diff --git a/subprojects/vala-unit/meson.build b/subprojects/vala-unit/meson.build index eb1975b3..f3160d5d 100644 --- a/subprojects/vala-unit/meson.build +++ b/subprojects/vala-unit/meson.build @@ -1,7 +1,7 @@ project( 'vala-unit', [ 'vala', 'c' ], - version: '1.0', + version: '2.0', license: 'LGPL2.1+', meson_version: '>= 0.50', ) @@ -20,8 +20,8 @@ add_project_arguments( language: 'vala' ) -target_vala = '0.44' -target_glib = '2.62' +target_vala = '0.56' +target_glib = '2.74' if not meson.get_compiler('vala').version().version_compare('>=' + target_vala) error('Vala does not meet minimum required version: ' + target_vala) @@ -61,7 +61,7 @@ test_sources = files( ) package_name = 'ValaUnit' -package_version = '1.0' +package_version = '2.0' package_full = '@0@-@1@'.format(package_name, package_version) package_vapi = '@0@-@1@'.format(meson.project_name(), package_version) package_gir = package_full + '.gir' diff --git a/subprojects/vala-unit/src/test-case.vala b/subprojects/vala-unit/src/test-case.vala index 9a7fc888..db4e9dbd 100644 --- a/subprojects/vala-unit/src/test-case.vala +++ b/subprojects/vala-unit/src/test-case.vala @@ -46,7 +46,7 @@ public abstract class ValaUnit.TestCase : GLib.Object, TestAssertions { public string name { get; private set; } /** The collection of GLib tests defined by this test case. */ - public GLib.TestSuite suite { get; private set; } + protected GLib.TestSuite suite; /** Main loop context for this test case. */ protected GLib.MainContext main_loop { @@ -204,4 +204,13 @@ public abstract class ValaUnit.TestCase : GLib.Object, TestAssertions { ); } + /** + * Steals the {@link GLib.TestSuite} that this test case wraps. + * + * After this method, you should *no longer* use this object! + */ + public GLib.TestSuite steal_suite() { + return (owned) this.suite; + } + } diff --git a/subprojects/vala-unit/test/test-driver.vala b/subprojects/vala-unit/test/test-driver.vala index 9b6f3698..5b195782 100644 --- a/subprojects/vala-unit/test/test-driver.vala +++ b/subprojects/vala-unit/test/test-driver.vala @@ -8,9 +8,9 @@ int main(string[] args) { Test.init(ref args); - TestSuite root = TestSuite.get_root(); - root.add_suite(new TestAssertions().suite); - root.add_suite(new CollectionAssertions().suite); + unowned TestSuite root = TestSuite.get_root(); + root.add_suite(new TestAssertions().steal_suite()); + root.add_suite(new CollectionAssertions().steal_suite()); MainLoop loop = new MainLoop (); diff --git a/test/meson.build b/test/meson.build index 17903a65..7bf5211f 100644 --- a/test/meson.build +++ b/test/meson.build @@ -126,6 +126,7 @@ test_integration_sources = [ test_engine_dependencies = [ config_dep, + glib, engine_internal_dep, vala_unit_dep, ] @@ -151,6 +152,7 @@ test_engine_bin = executable('test-engine', test_client_dependencies = [ config_dep, + glib, client_internal_dep, vala_unit_dep, ] @@ -166,6 +168,7 @@ test_client_bin = executable('test-client', test_js_dependencies = [ config_dep, + glib, client_internal_dep, vala_unit_dep, ] @@ -185,6 +188,7 @@ test_integration_bin = executable('test-integration', test_integration_sources, dependencies: [ config_dep, + glib, engine_dep, gee, gio, diff --git a/test/test-client.vala b/test/test-client.vala index 66b60665..b3685e9b 100644 --- a/test/test-client.vala +++ b/test/test-client.vala @@ -44,23 +44,23 @@ int main(string[] args) { // Keep this before other ClientWebView based tests since it tests // WebContext init - client.add_suite(new Accounts.ManagerTest().suite); - client.add_suite(new Application.CertificateManagerTest().suite); - client.add_suite(new Application.ClientTest().suite); - client.add_suite(new Application.ConfigurationTest().suite); - client.add_suite(new Components.WebViewTest().suite); - client.add_suite(new Components.ValidatorTest().suite); - client.add_suite(new Composer.WebViewTest().suite); - client.add_suite(new Composer.WidgetTest().suite); - client.add_suite(new Util.Cache.Test().suite); - client.add_suite(new Util.Email.Test().suite); - client.add_suite(new Util.JS.Test().suite); + client.add_suite(new Accounts.ManagerTest().steal_suite()); + client.add_suite(new Application.CertificateManagerTest().steal_suite()); + client.add_suite(new Application.ClientTest().steal_suite()); + client.add_suite(new Application.ConfigurationTest().steal_suite()); + client.add_suite(new Components.WebViewTest().steal_suite()); + client.add_suite(new Components.ValidatorTest().steal_suite()); + client.add_suite(new Composer.WebViewTest().steal_suite()); + client.add_suite(new Composer.WidgetTest().steal_suite()); + client.add_suite(new Util.Cache.Test().steal_suite()); + client.add_suite(new Util.Email.Test().steal_suite()); + client.add_suite(new Util.JS.Test().steal_suite()); /* * Run the tests */ - TestSuite root = TestSuite.get_root(); - root.add_suite(client); + unowned TestSuite root = TestSuite.get_root(); + root.add_suite((owned) client); int ret = -1; Idle.add(() => { diff --git a/test/test-engine.vala b/test/test-engine.vala index 699683b6..1a097562 100644 --- a/test/test-engine.vala +++ b/test/test-engine.vala @@ -28,75 +28,75 @@ int main(string[] args) { TestSuite engine = new TestSuite("engine"); - engine.add_suite(new Geary.AccountInformationTest().suite); - engine.add_suite(new Geary.AttachmentTest().suite); - engine.add_suite(new Geary.ContactHarvesterImplTest().suite); - engine.add_suite(new Geary.EngineTest().suite); - engine.add_suite(new Geary.FolderPathTest().suite); - engine.add_suite(new Geary.IdleManagerTest().suite); - engine.add_suite(new Geary.TimeoutManagerTest().suite); - engine.add_suite(new Geary.TlsNegotiationMethodTest().suite); - engine.add_suite(new Geary.App.ConversationTest().suite); - engine.add_suite(new Geary.App.ConversationSetTest().suite); + engine.add_suite(new Geary.AccountInformationTest().steal_suite()); + engine.add_suite(new Geary.AttachmentTest().steal_suite()); + engine.add_suite(new Geary.ContactHarvesterImplTest().steal_suite()); + engine.add_suite(new Geary.EngineTest().steal_suite()); + engine.add_suite(new Geary.FolderPathTest().steal_suite()); + engine.add_suite(new Geary.IdleManagerTest().steal_suite()); + engine.add_suite(new Geary.TimeoutManagerTest().steal_suite()); + engine.add_suite(new Geary.TlsNegotiationMethodTest().steal_suite()); + engine.add_suite(new Geary.App.ConversationTest().steal_suite()); + engine.add_suite(new Geary.App.ConversationSetTest().steal_suite()); // Depends on ConversationTest and ConversationSetTest passing - engine.add_suite(new Geary.App.ConversationMonitorTest().suite); - engine.add_suite(new Geary.Ascii.Test().suite); - engine.add_suite(new Geary.ConfigFileTest().suite); - engine.add_suite(new Geary.Db.DatabaseTest().suite); - engine.add_suite(new Geary.Db.VersionedDatabaseTest().suite); - engine.add_suite(new Geary.HTML.UtilTest().suite); + engine.add_suite(new Geary.App.ConversationMonitorTest().steal_suite()); + engine.add_suite(new Geary.Ascii.Test().steal_suite()); + engine.add_suite(new Geary.ConfigFileTest().steal_suite()); + engine.add_suite(new Geary.Db.DatabaseTest().steal_suite()); + engine.add_suite(new Geary.Db.VersionedDatabaseTest().steal_suite()); + engine.add_suite(new Geary.HTML.UtilTest().steal_suite()); // Other IMAP tests rely on these working, so test them first - engine.add_suite(new Geary.Imap.DataFormatTest().suite); + engine.add_suite(new Geary.Imap.DataFormatTest().steal_suite()); - engine.add_suite(new Geary.Imap.CreateCommandTest().suite); - engine.add_suite(new Geary.Imap.FetchCommandTest().suite); - engine.add_suite(new Geary.Imap.FetchDataDecoderTest().suite); - engine.add_suite(new Geary.Imap.ListParameterTest().suite); - engine.add_suite(new Geary.Imap.MailboxSpecifierTest().suite); - engine.add_suite(new Geary.Imap.NamespaceResponseTest().suite); + engine.add_suite(new Geary.Imap.CreateCommandTest().steal_suite()); + engine.add_suite(new Geary.Imap.FetchCommandTest().steal_suite()); + engine.add_suite(new Geary.Imap.FetchDataDecoderTest().steal_suite()); + engine.add_suite(new Geary.Imap.ListParameterTest().steal_suite()); + engine.add_suite(new Geary.Imap.MailboxSpecifierTest().steal_suite()); + engine.add_suite(new Geary.Imap.NamespaceResponseTest().steal_suite()); // Depends on IMAP commands working - engine.add_suite(new Geary.Imap.DeserializerTest().suite); - engine.add_suite(new Geary.Imap.ClientConnectionTest().suite); - engine.add_suite(new Geary.Imap.ClientSessionTest().suite); + engine.add_suite(new Geary.Imap.DeserializerTest().steal_suite()); + engine.add_suite(new Geary.Imap.ClientConnectionTest().steal_suite()); + engine.add_suite(new Geary.Imap.ClientSessionTest().steal_suite()); - engine.add_suite(new Geary.ImapDB.AccountTest().suite); - engine.add_suite(new Geary.ImapDB.AttachmentTest().suite); - engine.add_suite(new Geary.ImapDB.AttachmentIoTest().suite); - engine.add_suite(new Geary.ImapDB.DatabaseTest().suite); - engine.add_suite(new Geary.ImapDB.EmailIdentifierTest().suite); - engine.add_suite(new Geary.ImapDB.FolderTest().suite); + engine.add_suite(new Geary.ImapDB.AccountTest().steal_suite()); + engine.add_suite(new Geary.ImapDB.AttachmentTest().steal_suite()); + engine.add_suite(new Geary.ImapDB.AttachmentIoTest().steal_suite()); + engine.add_suite(new Geary.ImapDB.DatabaseTest().steal_suite()); + engine.add_suite(new Geary.ImapDB.EmailIdentifierTest().steal_suite()); + engine.add_suite(new Geary.ImapDB.FolderTest().steal_suite()); // Depends on ImapDB working - engine.add_suite(new Geary.FtsSearchQueryTest().suite); + engine.add_suite(new Geary.FtsSearchQueryTest().steal_suite()); - engine.add_suite(new Geary.ImapEngine.AccountProcessorTest().suite); - engine.add_suite(new Geary.ImapEngine.GenericAccountTest().suite); + engine.add_suite(new Geary.ImapEngine.AccountProcessorTest().steal_suite()); + engine.add_suite(new Geary.ImapEngine.GenericAccountTest().steal_suite()); // Depends on ImapDb.Database working correctly - engine.add_suite(new Geary.ContactStoreImplTest().suite); + engine.add_suite(new Geary.ContactStoreImplTest().steal_suite()); - engine.add_suite(new Geary.Inet.Test().suite); - engine.add_suite(new Geary.Mime.ContentTypeTest().suite); - engine.add_suite(new Geary.Outbox.EmailIdentifierTest().suite); - engine.add_suite(new Geary.RFC822.MailboxAddressTest().suite); - engine.add_suite(new Geary.RFC822.MailboxAddressesTest().suite); - engine.add_suite(new Geary.RFC822.MessageDataTest().suite); - engine.add_suite(new Geary.RFC822.PartTest().suite); - engine.add_suite(new Geary.RFC822.Utils.Test().suite); + engine.add_suite(new Geary.Inet.Test().steal_suite()); + engine.add_suite(new Geary.Mime.ContentTypeTest().steal_suite()); + engine.add_suite(new Geary.Outbox.EmailIdentifierTest().steal_suite()); + engine.add_suite(new Geary.RFC822.MailboxAddressTest().steal_suite()); + engine.add_suite(new Geary.RFC822.MailboxAddressesTest().steal_suite()); + engine.add_suite(new Geary.RFC822.MessageDataTest().steal_suite()); + engine.add_suite(new Geary.RFC822.PartTest().steal_suite()); + engine.add_suite(new Geary.RFC822.Utils.Test().steal_suite()); // Message requires all of the rest of the package working, so put // last - engine.add_suite(new Geary.RFC822.MessageTest().suite); - engine.add_suite(new Geary.String.Test().suite); - engine.add_suite(new Geary.EmailTest().suite); - engine.add_suite(new Geary.ComposedEmailTest().suite); + engine.add_suite(new Geary.RFC822.MessageTest().steal_suite()); + engine.add_suite(new Geary.String.Test().steal_suite()); + engine.add_suite(new Geary.EmailTest().steal_suite()); + engine.add_suite(new Geary.ComposedEmailTest().steal_suite()); /* * Run the tests */ - TestSuite root = TestSuite.get_root(); - root.add_suite(engine); + unowned TestSuite root = TestSuite.get_root(); + root.add_suite((owned) engine); MainLoop loop = new MainLoop (); diff --git a/test/test-integration.vala b/test/test-integration.vala index 43254714..8785d7ae 100644 --- a/test/test-integration.vala +++ b/test/test-integration.vala @@ -48,19 +48,19 @@ int main(string[] args) { switch (config.type) { case IMAP: - integration.add_suite(new Integration.Imap.ClientSession(config).suite); + integration.add_suite(new Integration.Imap.ClientSession(config).steal_suite()); break; case SMTP: - integration.add_suite(new Integration.Smtp.ClientSession(config).suite); + integration.add_suite(new Integration.Smtp.ClientSession(config).steal_suite()); break; } /* * Run the tests */ - TestSuite root = TestSuite.get_root(); - root.add_suite(integration); + unowned TestSuite root = TestSuite.get_root(); + root.add_suite((owned) integration); MainLoop loop = new MainLoop(); @@ -111,4 +111,4 @@ private Integration.Configuration load_config(string[] args) { ); } -} \ No newline at end of file +} diff --git a/test/test-js.vala b/test/test-js.vala index 7aa4fb1a..c3e0a7d4 100644 --- a/test/test-js.vala +++ b/test/test-js.vala @@ -42,15 +42,15 @@ int main(string[] args) { TestSuite js = new TestSuite("js"); - js.add_suite(new Components.PageStateTest().suite); - js.add_suite(new Composer.PageStateTest().suite); - js.add_suite(new ConversationPageStateTest().suite); + js.add_suite(new Components.PageStateTest().steal_suite()); + js.add_suite(new Composer.PageStateTest().steal_suite()); + js.add_suite(new ConversationPageStateTest().steal_suite()); /* * Run the tests */ - TestSuite root = TestSuite.get_root(); - root.add_suite(js); + unowned TestSuite root = TestSuite.get_root(); + root.add_suite((owned) js); int ret = -1; Idle.add(() => {