Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
- synchronize

jobs:
build:
build-and-test:

runs-on: ubuntu-22.04

Expand Down Expand Up @@ -36,9 +36,12 @@ jobs:
env:
DESTDIR: out
run: |
meson build -Ddocumentation=true
meson build -Ddocumentation=true -Dtests=true
ninja -C build
ninja -C build install
- name: Run Tests
run: |
meson test -v -C build

fedora:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -93,3 +96,4 @@ jobs:
io.elementary.vala-lint -d lib
io.elementary.vala-lint -d plugins
io.elementary.vala-lint -d src
io.elementary.vala-lint -d tests
3 changes: 3 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ subdir('plugins/template')
if get_option('documentation')
subdir('docs')
endif
if get_option('tests')
subdir('tests')
endif
subdir('po')

vapigen = find_program('vapigen', required: false)
Expand Down
1 change: 1 addition & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
option ('documentation', type : 'boolean', value : false)
option ('tests', type : 'boolean', value : false)
option ('systemd', type : 'boolean', value : true)
option ('systemduserunitdir', type : 'string', value : '')
option ('old-icon-groups', type : 'boolean', value : false)
52 changes: 52 additions & 0 deletions tests/TestCase.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2025 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-3.0-or-later
*/

/**
* A simple test case class. To use it inherit from it and add test methods
* in the constructor using {@link add_test}. Override {@link set_up} and {@link tear_down}
* to provide per-test-method setup and teardown. Then add a `main()` function
* and return the result of {@link run}.
*/
public abstract class Gala.TestCase : Object {
public delegate void TestMethod ();

public string name { get; construct; }

private GLib.TestSuite suite;

construct {
suite = new GLib.TestSuite (name);
}

public int run (string[] args) {
Test.init (ref args);
TestSuite.get_root ().add_suite ((owned) suite);
return Test.run ();
}

protected void add_test (string name, TestMethod test) {
var test_case = new GLib.TestCase (
name,
set_up,
(TestFixtureFunc) test,
tear_down
);

suite.add ((owned) test_case);
}

public virtual void set_up () {
}

public virtual void tear_down () {
}

public void assert_finalize_object<G> (ref G data) {
unowned var weak_pointer = data;
((Object) data).add_weak_pointer (&weak_pointer);
data = null;
assert_null (weak_pointer);
}
}
157 changes: 157 additions & 0 deletions tests/lib/PropertyTargetTest.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* Copyright 2025 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-3.0-or-later
*/

public class MockObject : Object {
public int int_value { get; set; }
public double double_value { get; set; }
}

public class Gala.PropertyTargetTest : TestCase {
private MockObject? target;
private PropertyTarget? default_int_prop_target;

public PropertyTargetTest () {
Object (name: "PropertyTarget");
}

construct {
add_test ("simple propagation", test_simple_propagation);
add_test ("double propagation", test_double_propagation);
add_test ("other actions", test_other_actions);
add_test ("finalize object first", test_finalize_object_first);
add_test ("finalize property target first", test_finalize_property_target_first);
}

public override void set_up () {
target = new MockObject ();
default_int_prop_target = new PropertyTarget (
MULTITASKING_VIEW,
target,
"int-value",
typeof (int),
0,
10
);
}

public override void tear_down () {
target = null;
default_int_prop_target = null;
}

private void test_simple_propagation () {
assert_nonnull (&default_int_prop_target);
assert_nonnull (&target);
assert_cmpint (target.int_value, EQ, 0);

default_int_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.0);
assert_cmpint (target.int_value, EQ, 0);

default_int_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.5);
assert_cmpint (target.int_value, EQ, 5);

default_int_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 1.0);
assert_cmpint (target.int_value, EQ, 10);

default_int_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.8);
assert_cmpint (target.int_value, EQ, 8);

default_int_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.3);
assert_cmpint (target.int_value, EQ, 3);

default_int_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.6);
assert_cmpint (target.int_value, EQ, 6);

assert_finalize_object<MockObject> (ref target);
assert_finalize_object<PropertyTarget> (ref default_int_prop_target);
}

private void test_double_propagation () {
var double_prop_target = new PropertyTarget (
MULTITASKING_VIEW,
target,
"double-value",
typeof (double),
0.0,
2.0
);

assert_nonnull (&double_prop_target);
assert_nonnull (&target);
assert_cmpfloat (target.double_value, EQ, 0.0);

double_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.0);
assert_cmpfloat (target.double_value, EQ, 0.0);

double_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.5);
assert_cmpfloat (target.double_value, EQ, 1.0);

double_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 1.0);
assert_cmpfloat (target.double_value, EQ, 2.0);

double_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.8);
assert_cmpfloat (target.double_value, EQ, 1.6);

double_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.3);
assert_cmpfloat (target.double_value, EQ, 0.6);

double_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.6);
assert_cmpfloat (target.double_value, EQ, 1.2);

assert_finalize_object<MockObject> (ref target);
assert_finalize_object<PropertyTarget> (ref double_prop_target);
}

private void test_other_actions () {
assert_nonnull (&default_int_prop_target);

assert_nonnull (&target);
assert_cmpint (target.int_value, EQ, 0);

default_int_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.0);
assert_cmpint (target.int_value, EQ, 0);

default_int_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.5);
assert_cmpint (target.int_value, EQ, 5);

default_int_prop_target.propagate (UPDATE, SWITCH_WORKSPACE, 1.0);
assert_cmpint (target.int_value, EQ, 5);

default_int_prop_target.propagate (UPDATE, CUSTOM, 1.0);
assert_cmpint (target.int_value, EQ, 5);

default_int_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 1.0);
assert_cmpint (target.int_value, EQ, 10);

assert_finalize_object<MockObject> (ref target);
assert_finalize_object<PropertyTarget> (ref default_int_prop_target);
}

private void test_finalize_object_first () {
assert_nonnull (&target);
assert_nonnull (&default_int_prop_target);

// We can finalize the object before the property target because it doesn't hold a strong reference to it
assert_finalize_object<MockObject> (ref target);

default_int_prop_target.propagate (UPDATE, MULTITASKING_VIEW, 0.5);

assert_finalize_object<PropertyTarget> (ref default_int_prop_target);
}

private void test_finalize_property_target_first () {
assert_nonnull (&target);
assert_nonnull (&default_int_prop_target);

// Finalize the property target before the object and make sure we don't have weak references
// to the object (i.e. we don't crash when finalizing the object)
assert_finalize_object<PropertyTarget> (ref default_int_prop_target);
assert_finalize_object<MockObject> (ref target);
}
}

public int main (string[] args) {
return new Gala.PropertyTargetTest ().run (args);
}
22 changes: 22 additions & 0 deletions tests/lib/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
lib_test_sources = files(
meson.project_source_root() / 'lib' / 'Gestures' / 'Gesture.vala',
meson.project_source_root() / 'lib' / 'Gestures' / 'GestureTarget.vala',
meson.project_source_root() / 'lib' / 'Gestures' / 'PropertyTarget.vala',
)

tests = [
'PropertyTargetTest',
]

foreach test : tests
test_executable = executable(
test,
'@[email protected]'.format(test),
common_test_sources,
lib_test_sources,
dependencies: gala_base_dep,
install: false,
)

test(test, test_executable, suite: ['Gala', 'Gala/lib'])
endforeach
5 changes: 5 additions & 0 deletions tests/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
common_test_sources = files(
'TestCase.vala',
)

subdir('lib')