diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 665e0d9..2f81ef4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,8 +21,10 @@ workflow: before_script: - export DEBIAN_FRONTEND=noninteractive - apt-get -y update + - apt-get -y upgrade - apt-get -y build-dep . - - apt-get -y install gcovr git + - '[ -z "${EXTRA_PKGS}" ] || echo "Extra packages: ${EXTRA_PKGS}"' + - apt-get -y install gcovr git build-essential ${EXTRA_PKGS} .image: &image image: @@ -33,7 +35,7 @@ workflow: - librem5:arm64 # Regular, full build -build:native-debian-trixie:full: +build:gcc:native-debian-trixie:full: <<: *tags <<: *image <<: *before_script @@ -42,32 +44,51 @@ build:native-debian-trixie:full: paths: - _build script: - - meson -Db_coverage=true --werror . _build - - ninja -C _build + - meson setup -Db_coverage=true --werror _build + - meson compile -C _build except: variables: - $PKG_ONLY == "1" # Minimal build for e.g. submodule usage -build:native-debian-trixie:lib: +build:gcc:native-debian-trixie:lib: <<: *tags <<: *image <<: *before_script stage: build script: - - meson --werror -Ddaemon=false -Dgtk_doc=false . _build - - ninja -C _build + - meson setup --werror -Ddaemon=false -Dgtk_doc=false _build + - meson compile -C _build except: variables: - $PKG_ONLY == "1" +# Build using clang +build:clang:native-debian-trixie:full: + variables: + EXTRA_PKGS: clang + <<: *tags + <<: *image + <<: *before_script + stage: build + artifacts: + paths: + - _build + script: + - CC=clang meson setup --werror _build + - meson compile -C _build + except: + variables: + - $PKG_ONLY == "1" + allow_failure: true + test:native-debian-trixie: <<: *tags <<: *image <<: *before_script stage: test needs: - - build:native-debian-trixie:full + - build:gcc:native-debian-trixie:full coverage: '/^\s+lines\.+:\s+([\d.]+\%)\s+/' script: - dbus-run-session ninja -C _build test coverage diff --git a/debian/control b/debian/control index 6bb67a4..3517659 100644 --- a/debian/control +++ b/debian/control @@ -15,9 +15,11 @@ Build-Depends: libgudev-1.0-dev, libgsound-dev, libjson-glib-dev, + libumockdev-dev, meson, pkg-config, python3-docutils , + umockdev, valac, Standards-Version: 4.6.2 Homepage: https://source.puri.sm/Librem5/feedbackd diff --git a/src/fbd-dev-led-multicolor.c b/src/fbd-dev-led-multicolor.c index 8432e5b..d48ddc0 100644 --- a/src/fbd-dev-led-multicolor.c +++ b/src/fbd-dev-led-multicolor.c @@ -24,7 +24,7 @@ /** * fbd-dev-led-multicolor: * - * A multicolor led using the kernels "multi_intensitiy" + * A multicolor led using the `multi_intensitiy` sysfs attribute */ typedef struct _FbdDevLedMulticolorPrivate { guint red_index; @@ -100,7 +100,6 @@ fbd_dev_led_start_periodic_multicolor (FbdDevLed *led, GUdevDevice *dev = fbd_dev_led_get_device (led); g_autofree char *intensity = NULL; g_autoptr (GError) err = NULL; - g_autofree gchar *str = NULL; gboolean success = FALSE; guint max_brightness; guint colors[] = { 0, 0, 0 }; diff --git a/src/fbd-dev-led.c b/src/fbd-dev-led.c index a68b3da..8c48e67 100644 --- a/src/fbd-dev-led.c +++ b/src/fbd-dev-led.c @@ -30,6 +30,11 @@ enum { }; static GParamSpec *props[PROP_LAST_PROP]; +/** + * FbdDevLed: + * + * A single color LED driven by Linux sysfs + */ typedef struct _FbdDevLedPrivate { GUdevDevice *dev; guint max_brightness; @@ -52,7 +57,7 @@ fbd_dev_led_probe_default (FbdDevLed *led, GError **error) { FbdDevLedPrivate *priv = fbd_dev_led_get_instance_private (led); const gchar *name, *path; - gboolean success; + gboolean success = FALSE; name = g_udev_device_get_name (priv->dev); /* We don't know anything about diffusors that can combine different @@ -67,7 +72,6 @@ fbd_dev_led_probe_default (FbdDevLed *led, GError **error) c = strrchr (enum_name, '_'); color = g_ascii_strdown (c+1, -1); if (g_strstr_len (name, -1, color)) { - g_autoptr (GError) err = NULL; guint brightness = g_udev_device_get_sysfs_attr_as_int (priv->dev, LED_MAX_BRIGHTNESS_ATTR); if (!brightness) diff --git a/src/fbd-theme-validate.c b/src/fbd-theme-validate.c index 94ba171..488a65e 100644 --- a/src/fbd-theme-validate.c +++ b/src/fbd-theme-validate.c @@ -12,6 +12,7 @@ #define BLURP "- A validator for feedback themes" +G_NORETURN static void print_version (void) { diff --git a/tests/data/umockdev/led-multicolor.umockdev b/tests/data/umockdev/led-multicolor.umockdev new file mode 100644 index 0000000..d66c679 --- /dev/null +++ b/tests/data/umockdev/led-multicolor.umockdev @@ -0,0 +1,46 @@ +P: /devices/platform/led-controller/leds/rgb:status +E: CURRENT_TAGS=:seat: +E: FEEDBACKD_TYPE=led +E: ID_FOR_SEAT=leds-platform-led-controller +E: ID_PATH=platform-led-controller +E: ID_PATH_TAG=platform-led-controller +E: OF_COMPATIBLE_N=0 +E: OF_FULLNAME=/led-controller/multi-led +E: OF_NAME=multi-led +E: SUBSYSTEM=leds +E: TAGS=:seat: +A: brightness=0\n +L: device=../../../led-controller +A: max_brightness=248\n +A: multi_index=blue green red\n +A: multi_intensity=248 0 0\n +A: pattern= +A: power/control=auto\n +A: power/runtime_active_time=0\n +A: power/runtime_status=unsupported\n +A: power/runtime_suspended_time=0\n +A: repeat=-1\n +A: trigger=none kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock disk-activity disk-read disk-write mtd nand-disk heartbeat backlight cpu cpu0 cpu1 cpu2 cpu3 panic mmc1 mmc0 usb-gadget usb-host tps6598x-source-psy-0-003f-online bq25890-charger-0-online max170xx_battery-charging-or-full max170xx_battery-charging max170xx_battery-full max170xx_battery-charging-blink-full-solid timer rfkill-any rfkill-none rfkill0 rfkill1 rfkill2 rfkill3 bluetooth-power [pattern] phy2rx phy2tx phy2assoc phy2radio rfkill6\n + +P: /devices/platform/led-controller +E: DRIVER=leds_pwm_multicolor +E: ID_PATH=platform-led-controller +E: ID_PATH_TAG=platform-led-controller +E: MODALIAS=of:Nled-controllerT(null)Cpwm-leds-multicolor +E: OF_COMPATIBLE_0=pwm-leds-multicolor +E: OF_COMPATIBLE_N=1 +E: OF_FULLNAME=/led-controller +E: OF_NAME=led-controller +E: SUBSYSTEM=platform +L: driver=../../../bus/platform/drivers/leds_pwm_multicolor +A: driver_override=(null)\n +A: modalias=of:Nled-controllerT(null)Cpwm-leds-multicolor\n +L: of_node=../../../firmware/devicetree/base/led-controller +A: power/control=auto\n +A: power/runtime_active_time=0\n +A: power/runtime_status=unsupported\n +A: power/runtime_suspended_time=0\n +L: supplier:platform:30670000.pwm=../../virtual/devlink/platform:30670000.pwm--platform:led-controller +L: supplier:platform:30680000.pwm=../../virtual/devlink/platform:30680000.pwm--platform:led-controller +L: supplier:platform:30690000.pwm=../../virtual/devlink/platform:30690000.pwm--platform:led-controller + diff --git a/tests/data/umockdev/led-simple.umockdev b/tests/data/umockdev/led-simple.umockdev new file mode 100644 index 0000000..1360284 --- /dev/null +++ b/tests/data/umockdev/led-simple.umockdev @@ -0,0 +1,75 @@ +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PURI4543:00/leds/blue:status +E: CURRENT_TAGS=:seat: +E: FEEDBACKD_TYPE=led +E: ID_FOR_SEAT=leds-acpi-PURI4543_00 +E: ID_PATH=acpi-PURI4543:00 +E: ID_PATH_TAG=acpi-PURI4543_00 +E: SUBSYSTEM=leds +E: TAGS=:seat: +A: brightness=0\n +L: device=../../../PURI4543:00 +A: max_brightness=255\n +A: pattern= +A: power/async=disabled\n +A: power/control=auto\n +A: power/runtime_active_kids=0\n +A: power/runtime_active_time=0\n +A: power/runtime_enabled=disabled\n +A: power/runtime_status=unsupported\n +A: power/runtime_suspended_time=0\n +A: power/runtime_usage=0\n +A: repeat=-1\n +A: trigger=none kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock disk-activity disk-read disk-write mtd nand-disk cpu cpu0 cpu1 cpu2 cpu3 cpu4 cpu5 cpu6 cpu7 panic usb-gadget usb-host BAT0-charging-or-full BAT0-charging BAT0-full BAT0-charging-blink-full-solid rc-feedback [pattern] AC-online audio-mute audio-micmute rfkill-any rfkill-none bluetooth-power phy2rx phy2tx phy2assoc phy2radio rfkill28 hci0-power rfkill52 r8169-0-200:00:link r8169-0-200:00:1Gbps r8169-0-200:00:100Mbps r8169-0-200:00:10Mbps\n + +P: /devices/LNXSYSTM:00/LNXSYBUS:00/PURI4543:00 +E: DRIVER=Librem EC ACPI Driver +E: ID_VENDOR_FROM_DATABASE=Purism SPC +E: MODALIAS=acpi:PURI4543: +E: SUBSYSTEM=acpi +L: driver=../../../../bus/acpi/drivers/Librem EC ACPI Driver +A: hid=PURI4543\n +A: modalias=acpi:PURI4543:\n +A: path=\\_SB_.LIEC\n +L: physical_node=../../../platform/PURI4543:00 +A: power/async=disabled\n +A: power/control=auto\n +A: power/runtime_active_kids=0\n +A: power/runtime_active_time=0\n +A: power/runtime_enabled=disabled\n +A: power/runtime_status=unsupported\n +A: power/runtime_suspended_time=0\n +A: power/runtime_usage=0\n +A: uid=0\n + +P: /devices/LNXSYSTM:00/LNXSYBUS:00 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation +E: MODALIAS=acpi:LNXSYBUS: +E: SUBSYSTEM=acpi +A: hid=LNXSYBUS\n +A: modalias=acpi:LNXSYBUS:\n +A: path=\\_SB_\n +A: power/async=disabled\n +A: power/control=auto\n +A: power/runtime_active_kids=0\n +A: power/runtime_active_time=0\n +A: power/runtime_enabled=disabled\n +A: power/runtime_status=unsupported\n +A: power/runtime_suspended_time=0\n +A: power/runtime_usage=0\n + +P: /devices/LNXSYSTM:00 +E: ID_VENDOR_FROM_DATABASE=The Linux Foundation +E: MODALIAS=acpi:LNXSYSTM: +E: SUBSYSTEM=acpi +A: hid=LNXSYSTM\n +A: modalias=acpi:LNXSYSTM:\n +A: path=\\\n +A: power/async=disabled\n +A: power/control=auto\n +A: power/runtime_active_kids=0\n +A: power/runtime_active_time=0\n +A: power/runtime_enabled=disabled\n +A: power/runtime_status=unsupported\n +A: power/runtime_suspended_time=0\n +A: power/runtime_usage=0\n + diff --git a/tests/meson.build b/tests/meson.build index 254f684..a8672a3 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -1,5 +1,12 @@ if get_option('tests') +umockdev_dep = dependency('umockdev-1.0') + +add_test_setup ('umockdev', + exe_wrapper: 'umockdev-wrapper', + is_default: true +) + test_env = environment() test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) @@ -66,18 +73,23 @@ test_fbd_link_args = [ test_fbd_deps = [ fbd_dep, + umockdev_dep, ] +# HW independent tests fbd_tests = [ 'fbd-feedback-profile', 'fbd-feedback-theme', 'fbd-event', 'fbd-theme-expander', + 'fbd-dev-led', ] foreach test : fbd_tests t = executable('test-@0@'.format(test), - ['test-@0@.c'.format(test), generated_dbus_sources[1]], + ['test-@0@.c'.format(test), + 'testlib.c', + generated_dbus_sources[1]], c_args : test_fbd_cflags, pie : true, link_args : test_fbd_link_args, @@ -86,7 +98,6 @@ foreach test : fbd_tests test(test, t, env : test_env_fbd) endforeach - endif # daemon endif diff --git a/tests/test-fbd-dev-led.c b/tests/test-fbd-dev-led.c new file mode 100644 index 0000000..c541218 --- /dev/null +++ b/tests/test-fbd-dev-led.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2024 The Phosh Developers + * SPDX-License-Identifier: GPL-3.0+ + * + * Author: Guido Günther + */ + +#include "fbd-feedback-led.h" +#include "fbd-dev-led.h" +#include "fbd-dev-led-multicolor.h" + +#include "testlib.h" + + +static void +test_fbd_dev_led_simple (FbdUmockdevFixture *fixture, gconstpointer unused) +{ + GUdevClient *client; + g_autolist (GUdevDevice) leds = NULL; + FbdDevLed *led; + g_autoptr (GError) err = NULL; + GUdevDevice *dev; + + client = g_udev_client_new ((const char *const []){ "leds", NULL}); + leds = g_udev_client_query_by_subsystem (client, "leds"); + + /* There should be a single device only */ + g_assert_cmpint (g_list_length (leds), ==, 1); + dev = G_UDEV_DEVICE (leds->data); + + g_assert_cmpstr (g_udev_device_get_property (dev, "FEEDBACKD_TYPE"), ==, "led"); + + led = fbd_dev_led_new (dev, &err); + g_assert_no_error (err); + g_assert_cmpint (fbd_dev_led_get_max_brightness (led), ==, 255); + g_assert_true (fbd_dev_led_has_color (led, FBD_FEEDBACK_LED_COLOR_BLUE)); + g_assert_true (fbd_dev_led_start_periodic (led, FBD_FEEDBACK_LED_COLOR_BLUE, 50, 50)); + g_assert_finalize_object (led); +} + + +static void +test_fbd_dev_led_multicolor (FbdUmockdevFixture *fixture, gconstpointer unused) +{ + GUdevClient *client; + g_autolist (GUdevDevice) leds = NULL; + FbdDevLed *led; + g_autoptr (GError) err = NULL; + GUdevDevice *dev; + + client = g_udev_client_new ((const char *const []){ "leds", NULL}); + leds = g_udev_client_query_by_subsystem (client, "leds"); + + /* There should be a single device only */ + g_assert_cmpint (g_list_length (leds), ==, 1); + dev = G_UDEV_DEVICE (leds->data); + + g_assert_cmpstr (g_udev_device_get_property (dev, "FEEDBACKD_TYPE"), ==, "led"); + + led = fbd_dev_led_multicolor_new (dev, &err); + g_assert_no_error (err); + g_assert_cmpint (fbd_dev_led_get_max_brightness (led), ==, 248); + g_assert_true (fbd_dev_led_has_color (led, FBD_FEEDBACK_LED_COLOR_RGB)); + g_assert_true (fbd_dev_led_start_periodic (led, FBD_FEEDBACK_LED_COLOR_BLUE, 50, 50)); + + g_assert_finalize_object (led); +} + + +gint +main (gint argc, gchar *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + FBD_UMOCKDEV_TEST_ADD ("/feedbackd/fbd/dev/led/simple", + test_fbd_dev_led_simple, + "led-simple"); + FBD_UMOCKDEV_TEST_ADD ("/feedbackd/fbd/dev/led/multicolor", + test_fbd_dev_led_multicolor, + "led-multicolor"); + + return g_test_run(); +} diff --git a/tests/testlib.c b/tests/testlib.c new file mode 100644 index 0000000..e97623e --- /dev/null +++ b/tests/testlib.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 The Phosh Developers + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Author: Guido Günther + */ + +#include "testlib.h" + +void +fbd_test_umockdev_setup (FbdUmockdevFixture *fixture, gconstpointer mockname) +{ + g_autofree char *path = NULL; + g_autoptr (GError) err = NULL; + gboolean success; + + fixture->testbed = umockdev_testbed_new (); + path = g_strdup_printf("%s/umockdev/%s.umockdev", TEST_DATA_DIR, (const char *)mockname); + + success = umockdev_testbed_add_from_file (fixture->testbed, path, &err); + g_assert_no_error (err); + g_assert_true (success); + + umockdev_testbed_enable (fixture->testbed); +} + + +void +fbd_test_umockdev_teardown (FbdUmockdevFixture *fixture, gconstpointer unused) +{ + umockdev_testbed_clear (fixture->testbed); + umockdev_testbed_disable (fixture->testbed); +} diff --git a/tests/testlib.h b/tests/testlib.h new file mode 100644 index 0000000..f59df47 --- /dev/null +++ b/tests/testlib.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Phosh Developers + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include +#include + +#pragma once + +G_BEGIN_DECLS + +typedef struct _FbdUdevMockFixture { + UMockdevTestbed *testbed; +} FbdUmockdevFixture; + + +void fbd_test_umockdev_setup (FbdUmockdevFixture *fixture, gconstpointer mockname); +void fbd_test_umockdev_teardown (FbdUmockdevFixture *fixture, gconstpointer unused); + +#define FBD_UMOCKDEV_TEST_ADD(name, func, f) g_test_add ((name), FbdUmockdevFixture, (f), \ + (gpointer)fbd_test_umockdev_setup, \ + (gpointer)(func), \ + (gpointer)fbd_test_umockdev_teardown) +G_END_DECLS