* bug#43252: 27.1; DBus properties lack type hints or overrides @ 2020-09-07 0:54 Hugh Daschbach 2020-09-07 7:48 ` Michael Albinus 2020-09-10 8:00 ` bug#43252: Fwd: " Michael Albinus 0 siblings, 2 replies; 52+ messages in thread From: Hugh Daschbach @ 2020-09-07 0:54 UTC (permalink / raw) To: 43252 In order to implement a service exposing interface "org.bluez.GattService1", I need to export the properties defined for that interface. (See, https://kernel.googlesource.com/pub/scm/bluetooth/bluez/+/refs/tags/5.55/doc/gatt-api.txt) There are two properties that require an object path: "Device", and "Includes". Since there is no type information associated with the registered property, introspection supplies its best guess. If the value is a string it is described as a :string, not an :object-path There doesn't seem to be any mechanism to register the property and have introspection describe it as as an :object-path. Am I missing something? Is this out of scope? Is there anyway to specify simple types for parameter values? Thanks, Hugh In GNU Emacs 27.1 (build 1, x86_64-pc-linux-gnu, X toolkit, Xaw3d scroll bars) of 2020-08-06 built on klaatu Repository revision: 86d8d76aa36037184db0b2897c434cdaab1a9ae8 Repository branch: emacs-27 Windowing system distributor 'The X.Org Foundation', version 11.0.12008000 System Description: Artix Linux Recent messages: [mu4e] Indexing completed; processed 0, updated 0, cleaned-up 0 Mark set [mu4e] Indexing... processed 2, updated 2 [mu4e] Indexing completed; processed 2, updated 2, cleaned-up 0 [mu4e] Found 19 matching messages Mark set C-x C-g is undefined Winner undo (1 / 199) Winner undo (2 / 198) Auto-saving...done Configured using: 'configure --with-x-toolkit=lucid' Configured features: XAW3D XPM JPEG TIFF GIF PNG RSVG SOUND GPM DBUS GSETTINGS GLIB NOTIFY INOTIFY ACL GNUTLS LIBXML2 FREETYPE HARFBUZZ M17N_FLT LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS LUCID X11 XDBE XIM MODULES THREADS LIBSYSTEMD JSON PDUMPER LCMS2 GMP Important settings: value of $LANG: en_US.UTF-8 locale-coding-system: utf-8-unix Major mode: Emacs-Lisp Minor modes in effect: pdf-occur-global-minor-mode: t global-magit-file-mode: t magit-file-mode: t magit-auto-revert-mode: t global-git-commit-mode: t async-bytecomp-package-mode: t ggtags-navigation-mode: t desktop-save-mode: t which-key-mode: t hungry-delete-mode: t paredit-mode: t amx-mode: t ivy-mode: t winner-mode: t shell-dirtrack-mode: t save-place-mode: t global-edit-server-edit-mode: t auto-insert-mode: t override-global-mode: t straight-use-package-mode: t straight-package-neutering-mode: t tooltip-mode: t global-eldoc-mode: t eldoc-mode: t electric-indent-mode: t mouse-wheel-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t column-number-mode: t line-number-mode: t transient-mark-mode: t abbrev-mode: t Load-path shadows: /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox hides /home/hugh/.config/emacs/straight/build/org/ox /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-texinfo hides /home/hugh/.config/emacs/straight/build/org/ox-texinfo /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-publish hides /home/hugh/.config/emacs/straight/build/org/ox-publish /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-org hides /home/hugh/.config/emacs/straight/build/org/ox-org /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-odt hides /home/hugh/.config/emacs/straight/build/org/ox-odt /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-md hides /home/hugh/.config/emacs/straight/build/org/ox-md /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-man hides /home/hugh/.config/emacs/straight/build/org/ox-man /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-latex hides /home/hugh/.config/emacs/straight/build/org/ox-latex /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-icalendar hides /home/hugh/.config/emacs/straight/build/org/ox-icalendar /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-html hides /home/hugh/.config/emacs/straight/build/org/ox-html /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-beamer hides /home/hugh/.config/emacs/straight/build/org/ox-beamer /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-ascii hides /home/hugh/.config/emacs/straight/build/org/ox-ascii /home/hugh/.config/emacs/straight/build/org-plus-contrib/org hides /home/hugh/.config/emacs/straight/build/org/org /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-timer hides /home/hugh/.config/emacs/straight/build/org/org-timer /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-tempo hides /home/hugh/.config/emacs/straight/build/org/org-tempo /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-table hides /home/hugh/.config/emacs/straight/build/org/org-table /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-src hides /home/hugh/.config/emacs/straight/build/org/org-src /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-refile hides /home/hugh/.config/emacs/straight/build/org/org-refile /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-protocol hides /home/hugh/.config/emacs/straight/build/org/org-protocol /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-plot hides /home/hugh/.config/emacs/straight/build/org/org-plot /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-pcomplete hides /home/hugh/.config/emacs/straight/build/org/org-pcomplete /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-num hides /home/hugh/.config/emacs/straight/build/org/org-num /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-mouse hides /home/hugh/.config/emacs/straight/build/org/org-mouse /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-mobile hides /home/hugh/.config/emacs/straight/build/org/org-mobile /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-macs hides /home/hugh/.config/emacs/straight/build/org/org-macs /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-macro hides /home/hugh/.config/emacs/straight/build/org/org-macro /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-list hides /home/hugh/.config/emacs/straight/build/org/org-list /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-lint hides /home/hugh/.config/emacs/straight/build/org/org-lint /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-keys hides /home/hugh/.config/emacs/straight/build/org/org-keys /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-inlinetask hides /home/hugh/.config/emacs/straight/build/org/org-inlinetask /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-indent hides /home/hugh/.config/emacs/straight/build/org/org-indent /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-id hides /home/hugh/.config/emacs/straight/build/org/org-id /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-habit hides /home/hugh/.config/emacs/straight/build/org/org-habit /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-goto hides /home/hugh/.config/emacs/straight/build/org/org-goto /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-footnote hides /home/hugh/.config/emacs/straight/build/org/org-footnote /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-feed hides /home/hugh/.config/emacs/straight/build/org/org-feed /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-faces hides /home/hugh/.config/emacs/straight/build/org/org-faces /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-entities hides /home/hugh/.config/emacs/straight/build/org/org-entities /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-element hides /home/hugh/.config/emacs/straight/build/org/org-element /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-duration hides /home/hugh/.config/emacs/straight/build/org/org-duration /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-datetree hides /home/hugh/.config/emacs/straight/build/org/org-datetree /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-ctags hides /home/hugh/.config/emacs/straight/build/org/org-ctags /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-crypt hides /home/hugh/.config/emacs/straight/build/org/org-crypt /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-compat hides /home/hugh/.config/emacs/straight/build/org/org-compat /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-colview hides /home/hugh/.config/emacs/straight/build/org/org-colview /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-clock hides /home/hugh/.config/emacs/straight/build/org/org-clock /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-capture hides /home/hugh/.config/emacs/straight/build/org/org-capture /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-attach hides /home/hugh/.config/emacs/straight/build/org/org-attach /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-attach-git hides /home/hugh/.config/emacs/straight/build/org/org-attach-git /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-archive hides /home/hugh/.config/emacs/straight/build/org/org-archive /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-agenda hides /home/hugh/.config/emacs/straight/build/org/org-agenda /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol hides /home/hugh/.config/emacs/straight/build/org/ol /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-w3m hides /home/hugh/.config/emacs/straight/build/org/ol-w3m /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-rmail hides /home/hugh/.config/emacs/straight/build/org/ol-rmail /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-mhe hides /home/hugh/.config/emacs/straight/build/org/ol-mhe /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-irc hides /home/hugh/.config/emacs/straight/build/org/ol-irc /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-info hides /home/hugh/.config/emacs/straight/build/org/ol-info /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-gnus hides /home/hugh/.config/emacs/straight/build/org/ol-gnus /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-eww hides /home/hugh/.config/emacs/straight/build/org/ol-eww /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-eshell hides /home/hugh/.config/emacs/straight/build/org/ol-eshell /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-docview hides /home/hugh/.config/emacs/straight/build/org/ol-docview /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-bibtex hides /home/hugh/.config/emacs/straight/build/org/ol-bibtex /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-bbdb hides /home/hugh/.config/emacs/straight/build/org/ol-bbdb /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob hides /home/hugh/.config/emacs/straight/build/org/ob /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-vala hides /home/hugh/.config/emacs/straight/build/org/ob-vala /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-tangle hides /home/hugh/.config/emacs/straight/build/org/ob-tangle /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-table hides /home/hugh/.config/emacs/straight/build/org/ob-table /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-stan hides /home/hugh/.config/emacs/straight/build/org/ob-stan /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-sqlite hides /home/hugh/.config/emacs/straight/build/org/ob-sqlite /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-sql hides /home/hugh/.config/emacs/straight/build/org/ob-sql /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-shen hides /home/hugh/.config/emacs/straight/build/org/ob-shen /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-shell hides /home/hugh/.config/emacs/straight/build/org/ob-shell /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-sed hides /home/hugh/.config/emacs/straight/build/org/ob-sed /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-screen hides /home/hugh/.config/emacs/straight/build/org/ob-screen /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-scheme hides /home/hugh/.config/emacs/straight/build/org/ob-scheme /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-sass hides /home/hugh/.config/emacs/straight/build/org/ob-sass /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ruby hides /home/hugh/.config/emacs/straight/build/org/ob-ruby /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ref hides /home/hugh/.config/emacs/straight/build/org/ob-ref /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-python hides /home/hugh/.config/emacs/straight/build/org/ob-python /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-processing hides /home/hugh/.config/emacs/straight/build/org/ob-processing /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-plantuml hides /home/hugh/.config/emacs/straight/build/org/ob-plantuml /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-picolisp hides /home/hugh/.config/emacs/straight/build/org/ob-picolisp /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-perl hides /home/hugh/.config/emacs/straight/build/org/ob-perl /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-org hides /home/hugh/.config/emacs/straight/build/org/ob-org /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-octave hides /home/hugh/.config/emacs/straight/build/org/ob-octave /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ocaml hides /home/hugh/.config/emacs/straight/build/org/ob-ocaml /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-mscgen hides /home/hugh/.config/emacs/straight/build/org/ob-mscgen /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-maxima hides /home/hugh/.config/emacs/straight/build/org/ob-maxima /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-matlab hides /home/hugh/.config/emacs/straight/build/org/ob-matlab /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-makefile hides /home/hugh/.config/emacs/straight/build/org/ob-makefile /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-lua hides /home/hugh/.config/emacs/straight/build/org/ob-lua /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-lob hides /home/hugh/.config/emacs/straight/build/org/ob-lob /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-lisp hides /home/hugh/.config/emacs/straight/build/org/ob-lisp /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-lilypond hides /home/hugh/.config/emacs/straight/build/org/ob-lilypond /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ledger hides /home/hugh/.config/emacs/straight/build/org/ob-ledger /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-latex hides /home/hugh/.config/emacs/straight/build/org/ob-latex /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-js hides /home/hugh/.config/emacs/straight/build/org/ob-js /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-java hides /home/hugh/.config/emacs/straight/build/org/ob-java /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-io hides /home/hugh/.config/emacs/straight/build/org/ob-io /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-hledger hides /home/hugh/.config/emacs/straight/build/org/ob-hledger /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-haskell hides /home/hugh/.config/emacs/straight/build/org/ob-haskell /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-groovy hides /home/hugh/.config/emacs/straight/build/org/ob-groovy /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-gnuplot hides /home/hugh/.config/emacs/straight/build/org/ob-gnuplot /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-fortran hides /home/hugh/.config/emacs/straight/build/org/ob-fortran /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-forth hides /home/hugh/.config/emacs/straight/build/org/ob-forth /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-exp hides /home/hugh/.config/emacs/straight/build/org/ob-exp /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-eval hides /home/hugh/.config/emacs/straight/build/org/ob-eval /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-eshell hides /home/hugh/.config/emacs/straight/build/org/ob-eshell /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-emacs-lisp hides /home/hugh/.config/emacs/straight/build/org/ob-emacs-lisp /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ebnf hides /home/hugh/.config/emacs/straight/build/org/ob-ebnf /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-dot hides /home/hugh/.config/emacs/straight/build/org/ob-dot /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ditaa hides /home/hugh/.config/emacs/straight/build/org/ob-ditaa /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-css hides /home/hugh/.config/emacs/straight/build/org/ob-css /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-core hides /home/hugh/.config/emacs/straight/build/org/ob-core /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-coq hides /home/hugh/.config/emacs/straight/build/org/ob-coq /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-comint hides /home/hugh/.config/emacs/straight/build/org/ob-comint /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-clojure hides /home/hugh/.config/emacs/straight/build/org/ob-clojure /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-calc hides /home/hugh/.config/emacs/straight/build/org/ob-calc /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-awk hides /home/hugh/.config/emacs/straight/build/org/ob-awk /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-asymptote hides /home/hugh/.config/emacs/straight/build/org/ob-asymptote /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-abc hides /home/hugh/.config/emacs/straight/build/org/ob-abc /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-R hides /home/hugh/.config/emacs/straight/build/org/ob-R /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-J hides /home/hugh/.config/emacs/straight/build/org/ob-J /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-C hides /home/hugh/.config/emacs/straight/build/org/ob-C /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-loaddefs hides /home/hugh/.config/emacs/straight/build/org/org-loaddefs /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-install hides /home/hugh/.config/emacs/straight/build/org/org-install /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-texinfo hides /usr/local/share/emacs/27.1/lisp/org/ox-texinfo /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-publish hides /usr/local/share/emacs/27.1/lisp/org/ox-publish /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-org hides /usr/local/share/emacs/27.1/lisp/org/ox-org /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-odt hides /usr/local/share/emacs/27.1/lisp/org/ox-odt /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-md hides /usr/local/share/emacs/27.1/lisp/org/ox-md /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-man hides /usr/local/share/emacs/27.1/lisp/org/ox-man /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-latex hides /usr/local/share/emacs/27.1/lisp/org/ox-latex /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-icalendar hides /usr/local/share/emacs/27.1/lisp/org/ox-icalendar /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-html hides /usr/local/share/emacs/27.1/lisp/org/ox-html /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox hides /usr/local/share/emacs/27.1/lisp/org/ox /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-beamer hides /usr/local/share/emacs/27.1/lisp/org/ox-beamer /home/hugh/.config/emacs/straight/build/org-plus-contrib/ox-ascii hides /usr/local/share/emacs/27.1/lisp/org/ox-ascii /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-timer hides /usr/local/share/emacs/27.1/lisp/org/org-timer /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-tempo hides /usr/local/share/emacs/27.1/lisp/org/org-tempo /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-table hides /usr/local/share/emacs/27.1/lisp/org/org-table /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-src hides /usr/local/share/emacs/27.1/lisp/org/org-src /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-protocol hides /usr/local/share/emacs/27.1/lisp/org/org-protocol /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-plot hides /usr/local/share/emacs/27.1/lisp/org/org-plot /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-pcomplete hides /usr/local/share/emacs/27.1/lisp/org/org-pcomplete /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-num hides /usr/local/share/emacs/27.1/lisp/org/org-num /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-mouse hides /usr/local/share/emacs/27.1/lisp/org/org-mouse /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-mobile hides /usr/local/share/emacs/27.1/lisp/org/org-mobile /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-macs hides /usr/local/share/emacs/27.1/lisp/org/org-macs /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-macro hides /usr/local/share/emacs/27.1/lisp/org/org-macro /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-list hides /usr/local/share/emacs/27.1/lisp/org/org-list /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-lint hides /usr/local/share/emacs/27.1/lisp/org/org-lint /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-keys hides /usr/local/share/emacs/27.1/lisp/org/org-keys /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-inlinetask hides /usr/local/share/emacs/27.1/lisp/org/org-inlinetask /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-indent hides /usr/local/share/emacs/27.1/lisp/org/org-indent /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-id hides /usr/local/share/emacs/27.1/lisp/org/org-id /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-habit hides /usr/local/share/emacs/27.1/lisp/org/org-habit /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-goto hides /usr/local/share/emacs/27.1/lisp/org/org-goto /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-footnote hides /usr/local/share/emacs/27.1/lisp/org/org-footnote /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-feed hides /usr/local/share/emacs/27.1/lisp/org/org-feed /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-faces hides /usr/local/share/emacs/27.1/lisp/org/org-faces /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-entities hides /usr/local/share/emacs/27.1/lisp/org/org-entities /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-element hides /usr/local/share/emacs/27.1/lisp/org/org-element /home/hugh/.config/emacs/straight/build/org-plus-contrib/org hides /usr/local/share/emacs/27.1/lisp/org/org /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-duration hides /usr/local/share/emacs/27.1/lisp/org/org-duration /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-datetree hides /usr/local/share/emacs/27.1/lisp/org/org-datetree /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-ctags hides /usr/local/share/emacs/27.1/lisp/org/org-ctags /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-crypt hides /usr/local/share/emacs/27.1/lisp/org/org-crypt /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-compat hides /usr/local/share/emacs/27.1/lisp/org/org-compat /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-colview hides /usr/local/share/emacs/27.1/lisp/org/org-colview /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-clock hides /usr/local/share/emacs/27.1/lisp/org/org-clock /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-capture hides /usr/local/share/emacs/27.1/lisp/org/org-capture /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-attach-git hides /usr/local/share/emacs/27.1/lisp/org/org-attach-git /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-attach hides /usr/local/share/emacs/27.1/lisp/org/org-attach /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-archive hides /usr/local/share/emacs/27.1/lisp/org/org-archive /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-agenda hides /usr/local/share/emacs/27.1/lisp/org/org-agenda /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-w3m hides /usr/local/share/emacs/27.1/lisp/org/ol-w3m /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-rmail hides /usr/local/share/emacs/27.1/lisp/org/ol-rmail /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-mhe hides /usr/local/share/emacs/27.1/lisp/org/ol-mhe /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-irc hides /usr/local/share/emacs/27.1/lisp/org/ol-irc /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-info hides /usr/local/share/emacs/27.1/lisp/org/ol-info /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-gnus hides /usr/local/share/emacs/27.1/lisp/org/ol-gnus /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-eww hides /usr/local/share/emacs/27.1/lisp/org/ol-eww /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-eshell hides /usr/local/share/emacs/27.1/lisp/org/ol-eshell /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol hides /usr/local/share/emacs/27.1/lisp/org/ol /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-docview hides /usr/local/share/emacs/27.1/lisp/org/ol-docview /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-bibtex hides /usr/local/share/emacs/27.1/lisp/org/ol-bibtex /home/hugh/.config/emacs/straight/build/org-plus-contrib/ol-bbdb hides /usr/local/share/emacs/27.1/lisp/org/ol-bbdb /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-vala hides /usr/local/share/emacs/27.1/lisp/org/ob-vala /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-tangle hides /usr/local/share/emacs/27.1/lisp/org/ob-tangle /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-table hides /usr/local/share/emacs/27.1/lisp/org/ob-table /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-stan hides /usr/local/share/emacs/27.1/lisp/org/ob-stan /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-sqlite hides /usr/local/share/emacs/27.1/lisp/org/ob-sqlite /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-sql hides /usr/local/share/emacs/27.1/lisp/org/ob-sql /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-shen hides /usr/local/share/emacs/27.1/lisp/org/ob-shen /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-shell hides /usr/local/share/emacs/27.1/lisp/org/ob-shell /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-sed hides /usr/local/share/emacs/27.1/lisp/org/ob-sed /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-screen hides /usr/local/share/emacs/27.1/lisp/org/ob-screen /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-scheme hides /usr/local/share/emacs/27.1/lisp/org/ob-scheme /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-sass hides /usr/local/share/emacs/27.1/lisp/org/ob-sass /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ruby hides /usr/local/share/emacs/27.1/lisp/org/ob-ruby /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-R hides /usr/local/share/emacs/27.1/lisp/org/ob-R /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ref hides /usr/local/share/emacs/27.1/lisp/org/ob-ref /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-python hides /usr/local/share/emacs/27.1/lisp/org/ob-python /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-processing hides /usr/local/share/emacs/27.1/lisp/org/ob-processing /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-plantuml hides /usr/local/share/emacs/27.1/lisp/org/ob-plantuml /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-picolisp hides /usr/local/share/emacs/27.1/lisp/org/ob-picolisp /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-perl hides /usr/local/share/emacs/27.1/lisp/org/ob-perl /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-org hides /usr/local/share/emacs/27.1/lisp/org/ob-org /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-octave hides /usr/local/share/emacs/27.1/lisp/org/ob-octave /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ocaml hides /usr/local/share/emacs/27.1/lisp/org/ob-ocaml /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-mscgen hides /usr/local/share/emacs/27.1/lisp/org/ob-mscgen /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-maxima hides /usr/local/share/emacs/27.1/lisp/org/ob-maxima /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-matlab hides /usr/local/share/emacs/27.1/lisp/org/ob-matlab /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-makefile hides /usr/local/share/emacs/27.1/lisp/org/ob-makefile /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-lua hides /usr/local/share/emacs/27.1/lisp/org/ob-lua /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-lob hides /usr/local/share/emacs/27.1/lisp/org/ob-lob /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-lisp hides /usr/local/share/emacs/27.1/lisp/org/ob-lisp /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-lilypond hides /usr/local/share/emacs/27.1/lisp/org/ob-lilypond /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ledger hides /usr/local/share/emacs/27.1/lisp/org/ob-ledger /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-latex hides /usr/local/share/emacs/27.1/lisp/org/ob-latex /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-js hides /usr/local/share/emacs/27.1/lisp/org/ob-js /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-J hides /usr/local/share/emacs/27.1/lisp/org/ob-J /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-java hides /usr/local/share/emacs/27.1/lisp/org/ob-java /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-io hides /usr/local/share/emacs/27.1/lisp/org/ob-io /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-hledger hides /usr/local/share/emacs/27.1/lisp/org/ob-hledger /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-haskell hides /usr/local/share/emacs/27.1/lisp/org/ob-haskell /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-groovy hides /usr/local/share/emacs/27.1/lisp/org/ob-groovy /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-gnuplot hides /usr/local/share/emacs/27.1/lisp/org/ob-gnuplot /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-fortran hides /usr/local/share/emacs/27.1/lisp/org/ob-fortran /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-forth hides /usr/local/share/emacs/27.1/lisp/org/ob-forth /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-exp hides /usr/local/share/emacs/27.1/lisp/org/ob-exp /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-eval hides /usr/local/share/emacs/27.1/lisp/org/ob-eval /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-eshell hides /usr/local/share/emacs/27.1/lisp/org/ob-eshell /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-emacs-lisp hides /usr/local/share/emacs/27.1/lisp/org/ob-emacs-lisp /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob hides /usr/local/share/emacs/27.1/lisp/org/ob /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ebnf hides /usr/local/share/emacs/27.1/lisp/org/ob-ebnf /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-dot hides /usr/local/share/emacs/27.1/lisp/org/ob-dot /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-ditaa hides /usr/local/share/emacs/27.1/lisp/org/ob-ditaa /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-css hides /usr/local/share/emacs/27.1/lisp/org/ob-css /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-core hides /usr/local/share/emacs/27.1/lisp/org/ob-core /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-coq hides /usr/local/share/emacs/27.1/lisp/org/ob-coq /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-comint hides /usr/local/share/emacs/27.1/lisp/org/ob-comint /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-clojure hides /usr/local/share/emacs/27.1/lisp/org/ob-clojure /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-C hides /usr/local/share/emacs/27.1/lisp/org/ob-C /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-calc hides /usr/local/share/emacs/27.1/lisp/org/ob-calc /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-awk hides /usr/local/share/emacs/27.1/lisp/org/ob-awk /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-asymptote hides /usr/local/share/emacs/27.1/lisp/org/ob-asymptote /home/hugh/.config/emacs/straight/build/org-plus-contrib/ob-abc hides /usr/local/share/emacs/27.1/lisp/org/ob-abc /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-loaddefs hides /usr/local/share/emacs/27.1/lisp/org/org-loaddefs /home/hugh/.config/emacs/straight/build/org-plus-contrib/org-install hides /usr/local/share/emacs/27.1/lisp/org/org-install /home/hugh/.config/emacs/straight/build/let-alist/let-alist hides /usr/local/share/emacs/27.1/lisp/emacs-lisp/let-alist Features: (shadow emacsbug sh-script smie python tramp-cmds rng-xsd xsd-regexp rng-cmpct rng-nxml rng-valid nxml-mode nxml-outln nxml-rap sgml-mode company-tng company transpose-frame autoload lisp-mnt descr-text gl-bluez-gatt dabbrev quail org-eldoc ol-eww ol-rmail ol-mhe ol-irc ol-info ol-gnus nnir ol-docview ol-bibtex bibtex ol-bbdb ol-w3m pdf-sync pdf-outline pdf-links pdf-history pdf-occur ibuf-ext pdf-isearch let-alist pdf-annot tablist tablist-filter semantic/wisent/comp semantic/wisent semantic/wisent/wisent semantic/util-modes semantic/util semantic semantic/tag semantic/lex semantic/fw mode-local cedet pdf-misc pdf-tools pdf-view pdf-cache pdf-info tq pdf-util rect epa-mail epa-file mailalias face-remap tabify man view timezone gnutls url-http url-gw url-cache url-auth eww mm-url magit-extras magit-bookmark magit-submodule magit-obsolete magit-blame magit-stash magit-reflog magit-bisect magit-push magit-pull magit-fetch magit-clone magit-remote magit-commit magit-sequence magit-notes magit-worktree magit-tag magit-merge magit-branch magit-reset magit-files magit-refs magit-status magit package url-handlers magit-repos magit-apply magit-wip magit-log which-func imenu magit-diff smerge-mode diff magit-core magit-autorevert autorevert magit-margin magit-transient magit-process magit-mode git-commit transient magit-git magit-section magit-utils crm log-edit pcvs-util add-log with-editor async-bytecomp async tmm eieio-opt speedbar sb-image ezimage dframe dbus-bluetooth dbus-formatters dbus-inspector tree-mode flyspell repeat bug-reference macrostep-c cmacexp macrostep ggtags etags fileloop ewoc cc-mode cc-fonts cc-guess cc-menus cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs pulse xref project debug backtrace dired-aux tramp-cache tramp-sh tramp tramp-loaddefs trampver tramp-integration files-x tramp-compat ls-lisp recentf tree-widget visual-fill-column sort gnus-cite smiley shr-color qp mm-archive mail-extr gnus-art mm-uu mml2015 mm-view mml-smime smime dig gnus-sum gnus-group gnus-undo gnus-start gnus-cloud nnimap nnmail mail-source utf7 netrc nnoo parse-time iso8601 gnus-spec gnus-int gnus-range gnus-win gnus nnheader iso-transl csv executable disp-table network-stream nsm cl-print ace-window avy rcirc help-fns radix-tree persistent-soft list-utils pcache eieio-compat eieio-base font-utils unicode-fonts misearch multi-isearch two-column vc-git diff-mode elfeed-org elfeed-show elfeed-search bookmark elfeed-csv elfeed elfeed-curl url url-proxy url-expand url-methods url-history mailcap elfeed-log elfeed-db elfeed-lib url-queue xml-query mu4e mu4e-org mu4e-main mu4e-view mu4e-headers mu4e-compose mu4e-context mu4e-draft mu4e-actions ido rfc2368 smtpmail sendmail mu4e-mark mu4e-proc mu4e-utils doc-view jka-compr image-mode exif mu4e-lists mu4e-message flow-fill ox-reveal desktop frameset ox-hugo org-refile ffap thingatpt ox-blackfriday ox-odt rng-loc rng-uri rng-parse rng-match rng-dt rng-util rng-pttrn nxml-parse nxml-ns nxml-enc xmltok nxml-util ox-md ox-html table ox-beamer ox-latex ox-ascii ox-publish ox org-element avl-tree generator org org-macro org-footnote org-pcomplete org-list org-faces org-entities noutline outline ob-gnuplot ob-dot ob-ditaa ob-shell ob-awk ob-calc calc-store calc-trail calc-ext calc calc-loaddefs calc-macs ob ob-tangle org-src ob-ref ob-lob ob-table ob-exp ob-comint ob-emacs-lisp ob-core ob-eval org-table ol org-keys org-compat org-macs org-loaddefs find-func cal-menu calendar cal-loaddefs mule-util hl-line mu4e-vars message rmc format-spec rfc822 mml mml-sec epa derived epg epg-config gnus-util rmail rmail-loaddefs time-date mm-decode mm-bodies mm-encode mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr mailabbrev mail-utils gmm-utils mailheader mu4e-meta which-key server hungry-delete paredit ivy-posframe posframe ivy-hydra amx ivy flx delsel ivy-faces ivy-overlay colir color winner url-privacy filenotify slime-company-autoloads slime-autoloads macrostep-autoloads shr text-property-search url-cookie url-domsuf url-util url-parse auth-source eieio eieio-core eieio-loaddefs password-cache url-vars puny svg dom zenburn-theme zenburn-theme-autoloads which-key-autoloads visual-fill-column-autoloads unicode-fonts-autoloads ucs-utils-autoloads font-utils-autoloads persistent-soft-autoloads list-utils-autoloads cl pcache-autoloads tree-mode-autoloads transpose-frame-autoloads tex-mode shell pcomplete smtpmail-multi-autoloads smart-mode-line-respectful-theme smart-mode-line rich-minority smart-mode-line-autoloads rich-minority-autoloads saveplace ripgrep-autoloads restclient-autoloads pdf-tools-autoloads tablist-autoloads paredit-autoloads ox-reveal-autoloads ox-hugo-autoloads org-gcal-autoloads persist-autoloads request-deferred-autoloads deferred-autoloads request-autoloads org-caldav-autoloads org-plus-contrib-autoloads magit-svn-autoloads json-mode-autoloads json-snatcher-autoloads json-reformat-autoloads ix grapnel ix-autoloads grapnel-autoloads ivy-posframe-autoloads posframe-autoloads ivy-hydra-autoloads ispell ielm pp ibuffer ibuffer-loaddefs hyperbole-autoloads kotl-autoloads hydra lv hydra-autoloads lv-autoloads hungry-delete-autoloads gnuplot-autoloads ggtags-autoloads geiser-autoloads flx-autoloads forge-autoloads markdown-mode-autoloads magit-autoloads git-commit-autoloads with-editor-autoloads transient-autoloads async-autoloads ghub-autoloads treepy-autoloads let-alist-autoloads closql-autoloads emacsql-sqlite-autoloads emacsql-autoloads esup-autoloads elpher-autoloads emojify apropos tar-mode arc-mode archive-mode pcase json map ht emojify-autoloads ht-autoloads emms-autoloads elfeed-org-autoloads org-autoloads org-version elfeed-autoloads edit-server advice edit-server-autoloads dmenu-autoloads deft-autoloads dired-x use-package-ensure dired-subtree-autoloads dired-hacks-utils-autoloads diminish diminish-autoloads dictionary-autoloads link-autoloads connection-autoloads delight-autoloads deadgrep-autoloads spinner-autoloads dbus-inspector-autoloads dash-functional dash-functional-autoloads csv-autoloads counsel-projectile-autoloads projectile-autoloads pkg-info-autoloads epl-autoloads counsel-autoloads swiper-autoloads ivy-autoloads company-quickhelp-autoloads pos-tip-autoloads company-autoloads use-package-diminish autoinsert amx-autoloads alert log4e rx notifications dbus xml gntp alert-autoloads log4e-autoloads gntp-autoloads ag vc-svn compile comint ansi-color ring find-dired s dash dired dired-loaddefs ag-autoloads s-autoloads dash-autoloads adaptive-wrap adaptive-wrap-autoloads ace-window-autoloads avy-autoloads finder-inf edmacro kmacro browse-url cus-edit cus-start cus-load wid-edit use-package-bind-key bind-key easy-mmode cl-seq use-package-core use-package-autoloads bind-key-autoloads straight-autoloads info cl-extra help-mode easymenu seq byte-opt straight subr-x cl-macs gv cl-loaddefs cl-lib bytecomp byte-compile cconv early-init tooltip eldoc electric uniquify ediff-hook vc-hooks lisp-float-type mwheel term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe tabulated-list replace newcomment text-mode elisp-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow isearch timer select scroll-bar mouse jit-lock font-lock syntax facemenu font-core term/tty-colors frame minibuffer cl-generic cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese composite charscript charprop case-table epa-hook jka-cmpr-hook help simple abbrev obarray cl-preloaded nadvice loaddefs button faces cus-face macroexp files text-properties overlay sha1 md5 base64 format env code-pages mule custom widget hashtable-print-readable backquote threads dbusbind inotify lcms2 dynamic-setting system-font-setting font-render-setting x-toolkit x multi-tty make-network-process emacs) Memory information: ((conses 16 2346615 242711) (symbols 48 72629 6) (strings 32 326956 25390) (string-bytes 1 11416553) (vectors 16 122495) (vector-slots 8 2358061 258976) (floats 8 5596 2288) (intervals 56 234189 8288) (buffers 1000 244)) ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-07 0:54 bug#43252: 27.1; DBus properties lack type hints or overrides Hugh Daschbach @ 2020-09-07 7:48 ` Michael Albinus 2020-09-07 17:35 ` Hugh Daschbach 2020-09-10 8:00 ` bug#43252: Fwd: " Michael Albinus 1 sibling, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-07 7:48 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, > In order to implement a service exposing interface > "org.bluez.GattService1", I need to export the properties defined for > that interface. (See, > https://kernel.googlesource.com/pub/scm/bluetooth/bluez/+/refs/tags/5.55/doc/gatt-api.txt) > > There are two properties that require an object path: "Device", and > "Includes". Since there is no type information associated with the > registered property, introspection supplies its best guess. If the > value is a string it is described as a :string, not an :object-path > > There doesn't seem to be any mechanism to register the property and have > introspection describe it as as an :object-path. > > Am I missing something? Is this out of scope? Is there anyway to > specify simple types for parameter values? Confirmed. In `dbus-registered-objects-table', properties are stored w/o signature. An object path is stored as string, and dbus-get-property returns a string. Introspection data could be used if exists (like in your case). But they are optional, so one cannot trust on their existence. Maybe we could say that, in absence of introspection data, ofD.Properties.Get and ofD.Properties.GetAll shall return a default type, like string in case of object paths? Then it would be the responsibility of the user to provide proper introspection data if needed. > Thanks, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-07 7:48 ` Michael Albinus @ 2020-09-07 17:35 ` Hugh Daschbach 2020-09-07 18:00 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-07 17:35 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > >> There doesn't seem to be any mechanism to register the property >> and have >> introspection describe it as as an :object-path. >> > > Confirmed. In `dbus-registered-objects-table', properties are > stored w/o > signature. An object path is stored as string, and > dbus-get-property > returns a string. > > Introspection data could be used if exists (like in your > case). But they > are optional, so one cannot trust on their existence. Maybe we > could say > that, in absence of introspection data, ofD.Properties.Get and > ofD.Properties.GetAll shall return a default type, like string > in case > of object paths? Then it would be the responsibility of the user > to > provide proper introspection data if needed. > I had considered an optional or keyword argument to dbus-register-property, but I like introspection even more. Then the application simply registers ofD.Introspectable.Introspect for each of its objects? Introspect returns XML. The SEXP that dbus-introspect-xml returns is easier to work with. So do you memoize the returned value? There may not be enough overhead to be concerned. I'm just trying to imagine what overhead would be introduced. I'm looking at emulating a Bluetooth keyboard. So I'm anticipating bursty property updates on the order of tens per second. User initiated, rather than continuous background activity. But I don't want to bog the system down. An introspection per property update probably isn't much to worry about. Sounds good to me. Cheer, Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-07 17:35 ` Hugh Daschbach @ 2020-09-07 18:00 ` Michael Albinus 2020-09-07 19:18 ` Hugh Daschbach 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-07 18:00 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >>> There doesn't seem to be any mechanism to register the property and >>> have >>> introspection describe it as as an :object-path. >>> >> >> Confirmed. In `dbus-registered-objects-table', properties are stored >> w/o >> signature. An object path is stored as string, and dbus-get-property >> returns a string. >> >> Introspection data could be used if exists (like in your case). But >> they >> are optional, so one cannot trust on their existence. Maybe we could >> say >> that, in absence of introspection data, ofD.Properties.Get and >> ofD.Properties.GetAll shall return a default type, like string in >> case >> of object paths? Then it would be the responsibility of the user to >> provide proper introspection data if needed. >> > > I had considered an optional or keyword argument to > dbus-register-property, but I like introspection even more. Then the > application simply registers ofD.Introspectable.Introspect for each of > its objects? I'm just sitting at this. Yes, introspection data is the best way to go. I've already extended dbus-introspect-get-signature to support also properties (it does already work for methods and signals, modulo a bug I have fixed this way). Looks promising. > Introspect returns XML. The SEXP that dbus-introspect-xml returns is > easier to work with. Sure. But there are several helper functions, like the just mentioned dbus-introspect-get-signature. Have a look at dbus.el; not everything is documented. (And since I'm bad in documentation; comments for improvements are appreciated) > So do you memoize the returned value? There may not be enough > overhead to be concerned. I'm just trying to imagine what overhead > would be introduced. Not yet. But in case of performance problems, we could indeed do caching. > I'm looking at emulating a Bluetooth keyboard. So I'm anticipating > bursty property updates on the order of tens per second. User > initiated, rather than continuous background activity. But I don't > want to bog the system down. An introspection per property update > probably isn't much to worry about. My experience is that method calls are very responsive. But I haven't tested with bulk data yet, we'll see. Another problem: The changes I apply do not qualify as bug fixing any longer, so I fear they are not applicable to Emacs 27. I'm working on Emacs' master branch (what will be Emacs 28 later), the patches I have provided to you were backports. Do you have a chance to use Emacs' master branch? This will avoid discussions with the maintainers whether those changes are good for Emacs 27, and it will simplify my life considerably, because the sources for D-Bus in Emacs 27 and 28 differ. I have even applied changes to dbusbind.c, which means it would be harder for you to integrate my patches into Emacs 27. > Cheer, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-07 18:00 ` Michael Albinus @ 2020-09-07 19:18 ` Hugh Daschbach 2020-09-08 14:36 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-07 19:18 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > > Another problem: The changes I apply do not qualify as bug > fixing any > longer, so I fear they are not applicable to Emacs 27. I'm > working on > Emacs' master branch (what will be Emacs 28 later), the patches > I have > provided to you were backports. Do you have a chance to use > Emacs' > master branch? This will avoid discussions with the maintainers > whether > those changes are good for Emacs 27, and it will simplify my > life > considerably, because the sources for D-Bus in Emacs 27 and 28 > differ. I > have even applied changes to dbusbind.c, which means it would be > harder > for you to integrate my patches into Emacs 27. This all sounds good. I'd be happy to move my testing to master. I'd already realized that part of what I depend on won't make it to 27. I'll build master this afternoon. Thanks. Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-07 19:18 ` Hugh Daschbach @ 2020-09-08 14:36 ` Michael Albinus 2020-09-09 4:10 ` Hugh Daschbach 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-08 14:36 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >> Another problem: The changes I apply do not qualify as bug fixing any >> longer, so I fear they are not applicable to Emacs 27. I'm working on >> Emacs' master branch (what will be Emacs 28 later), the patches I >> have provided to you were backports. Do you have a chance to use >> Emacs' master branch? This will avoid discussions with the >> maintainers whether those changes are good for Emacs 27, and it will >> simplify my life considerably, because the sources for D-Bus in Emacs >> 27 and 28 differ. I have even applied changes to dbusbind.c, which >> means it would be harder for you to integrate my patches into Emacs >> 27. > > This all sounds good. I'd be happy to move my testing to master. I'd > already realized that part of what I depend on won't make it to 27. I've pushed a fix to master, which shall solve the problem. Playing with introspection, I found the problem that it stalls if there are no introspection data. Not applicable. So I've turned to the alternative approach, allowing type symbols in `dbus-set-property' and `dbus-register-property'. You could call now (dbus-register-property :session "org.gnu.Emacs" "/node1" "org.bluez.GattService1" "Device" :readwrite :object-path "/path/node1") Similar in `dbus-set-property'. Documentation is adapted, dbus-tests.el extended accordingly. > I'll build master this afternoon. Good luck! If everything goes well, could you pls check whther this problem is solved? > Thanks. > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-08 14:36 ` Michael Albinus @ 2020-09-09 4:10 ` Hugh Daschbach 2020-09-09 4:25 ` Hugh Daschbach 2020-09-09 13:25 ` Michael Albinus 0 siblings, 2 replies; 52+ messages in thread From: Hugh Daschbach @ 2020-09-09 4:10 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 [-- Attachment #1: Type: text/plain, Size: 1770 bytes --] Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > > I've pushed a fix to master, which shall solve the > problem. Playing with > introspection, I found the problem that it stalls if there are > no > introspection data. Not applicable. So I've turned to the > alternative > approach, allowing type symbols in `dbus-set-property' and > `dbus-register-property'. You could call now > > (dbus-register-property :session "org.gnu.Emacs" "/node1" > "org.bluez.GattService1" "Device" :readwrite > :object-path "/path/node1") > > Similar in `dbus-set-property'. Documentation is adapted, > dbus-tests.el > extended accordingly. Thanks, Michael. I think I still have issues. The attached script generates two boolean properties, then issues a GetManagedObjects method call. The two properties are not returned, though they are in the registered objects table. The script also drops an elisp ‘dbus-get-all-managed-objects’ request in the *scratch* buffer. If I execute that, I get a similar failure to #43251. That may not be surprising. I’m working an a more comprehensive test that registers the variety of types I need to support. I’ll post that when I have something worth looking at. I’d like to present that in a form compatible with dbus-test.el rather than throw more one off scripts at you. So give me a bit. I think the mechanism you implemented works well for simple types. Is there a mechanism to specify the signature for an empty compound type? I need arrays and dictionaries of various types. For something like a byte array, I expect I’ll need to interleave the :byte type between each value in the array. Correct? Thanks, Hugh [-- Attachment #2: GetManagedObjects test. --] [-- Type: text/plain, Size: 2300 bytes --] ;;; register-property-test.el --- Test program for complex :dict-entry. -*- lexical-binding: t; -*- ;; Copyright (C) 2020 Hugh Daschbach ;; Author: Hugh Daschbach <hugh@ccss.com> ;; Keywords: tools ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see <https://www.gnu.org/licenses/>. ;;; Commentary: ;; This program demonstrates an error in handling D-Bus properties ;; interface. ;; ;;; Code: (require 'dbus) (dbus-register-service :system "org.gnu.Emacs") (defun main () (interactive) (setq dbus-debug t) (setq debug-on-error t) ;; Boolean (dbus-register-property :system "org.gnu.Emacs" "/org/gnu/Emacs/hci0/dev_45_6d_61_63_73_01/service0002/characteristic0003" "org.bluez.GattCharacteristic1" "Discoverable-untyped" :read nil t) (dbus-register-property :system "org.gnu.Emacs" "/org/gnu/Emacs/hci0/dev_45_6d_61_63_73_01/service0002/characteristic0003" "org.bluez.GattCharacteristic1" "Discoverable-typed" :read :boolean nil t) (sit-for 1) (start-process "gmo" "*GMO*" "dbus-send" "--system" "--print-reply" "--type=method_call" "--system" "--dest=org.gnu.Emacs" "/" "org.freedesktop.DBus.ObjectManager.GetManagedObjects") (switch-to-buffer "*scratch*") (insert "(pp (dbus-get-all-managed-objects :system \"org.gnu.Emacs\" \"/\"))\n") (sit-for 1) (split-window-right) (switch-to-buffer "*GMO*") (goto-char (point-min))) (provide 'register-property-test) ;;; register-property-test.el ends here ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-09 4:10 ` Hugh Daschbach @ 2020-09-09 4:25 ` Hugh Daschbach 2020-09-09 13:25 ` Michael Albinus 1 sibling, 0 replies; 52+ messages in thread From: Hugh Daschbach @ 2020-09-09 4:25 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Hugh Daschbach writes: > Michael Albinus writes: > > Thanks, Michael. I think I still have issues. > > The attached script generates two boolean properties, then > issues > a GetManagedObjects method call. The two properties are not > returned, though they are in the registered objects table. My apologies. I left off the script invocation: ./src/emacs -q -Q --load ~/.config/emacs/register-property-test.el --eval "(main)" > The script also drops an elisp ‘dbus-get-all-managed-objects’ > request in > the *scratch* buffer. If I execute that, I get a similar > failure > to #43251. That may not be surprising. And please ignore the above paragraph. That was an operator error. Thanks, Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-09 4:10 ` Hugh Daschbach 2020-09-09 4:25 ` Hugh Daschbach @ 2020-09-09 13:25 ` Michael Albinus 2020-09-09 16:12 ` Hugh Daschbach 1 sibling, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-09 13:25 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, > The attached script generates two boolean properties, then issues a > GetManagedObjects method call. The two properties are not returned, > though they are in the registered objects table. Thanks for the heads up. There was still a small thinko in dbus-managed-objects-handler which I haven't noticed, because in my tests I have registered both methods and properties in parallel. I've pushed a fix to master, including extension of dbus-tests.el (which shall prevent this problem to reappear silently). > The script also drops an elisp ‘dbus-get-all-managed-objects’ request > in > the *scratch* buffer. If I execute that, I get a similar failure to > #43251. That may not be surprising. Sure. I haven't worked on this yet. > I’m working an a more comprehensive test that registers the variety of > types I need to support. I’ll post that when I have something worth > looking at. I’d like to present that in a form compatible with > dbus-test.el rather than throw more one off scripts at you. So give > me > a bit. That would be great! I'll happily add your tests to dbus-tests.el. However, this would be a contribution to Emacs. For contributions exceeding ~15 lines, every contributor shall sign the legal papers from the FSF. Would you be willing to do? > I think the mechanism you implemented works well for simple types. Is > there a mechanism to specify the signature for an empty compound type? > I need arrays and dictionaries of various types. Until now, the implementation allows only basic D-Bus types for properties. Nobody has asked for more so far :-) I could extend this for complex types. Since this will require internal changes of data structures, it might take some days. An empty array could be specified by the element's signature, like (:array :signature "{sv}"). See the D-Bus manual via (info "(dbus) Type Conversion") > For something like a byte array, I expect I’ll need to interleave the > :byte type between each value in the array. Correct? Yes. > Thanks, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-09 13:25 ` Michael Albinus @ 2020-09-09 16:12 ` Hugh Daschbach 2020-09-09 17:43 ` Michael Albinus [not found] ` <874ko6979w.fsf@gmx.de> 0 siblings, 2 replies; 52+ messages in thread From: Hugh Daschbach @ 2020-09-09 16:12 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > > That would be great! I'll happily add your tests to > dbus-tests.el. However, this would be a contribution to > Emacs. For > contributions exceeding ~15 lines, every contributor shall sign > the > legal papers from the FSF. Would you be willing to do? Yes, I'd be willing to assign copyright to FSF. Where do I get a copy of the paperwork? I'll keep submissions to under 15 lines until I can get the paperwork cleared. > Until now, the implementation allows only basic D-Bus types for > properties. Nobody has asked for more so far :-) > > I could extend this for complex types. Since this will require > internal > changes of data structures, it might take some days. > > An empty array could be specified by the element's signature, > like > (:array :signature "{sv}"). See the D-Bus manual via > (info "(dbus) Type Conversion") I have used that signature for method returns. I suppose I could save the signature as a property value instead of nil if I have an empty value for a compound type. Let me look at that. Thanks again. Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-09 16:12 ` Hugh Daschbach @ 2020-09-09 17:43 ` Michael Albinus [not found] ` <874ko6979w.fsf@gmx.de> 1 sibling, 0 replies; 52+ messages in thread From: Michael Albinus @ 2020-09-09 17:43 UTC (permalink / raw) To: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >> >> That would be great! I'll happily add your tests to >> dbus-tests.el. However, this would be a contribution to Emacs. For >> contributions exceeding ~15 lines, every contributor shall sign the >> legal papers from the FSF. Would you be willing to do? > > Yes, I'd be willing to assign copyright to FSF. Where do I get a copy > of the paperwork? I'll keep submissions to under 15 lines until I can > get the paperwork cleared. FTR, template sent offlist. > Thanks again. > > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
[parent not found: <874ko6979w.fsf@gmx.de>]
[parent not found: <87v9gm9x9i.fsf@ccss.com>]
* bug#43252: 27.1; DBus properties lack type hints or overrides [not found] ` <87v9gm9x9i.fsf@ccss.com> @ 2020-09-10 14:59 ` Michael Albinus 2020-09-10 16:57 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-10 14:59 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, > In the meantime, just to check that I'm on the right track, I've > attached a failing test. Sadly, it's more than 15 lines. Feel free > to test with it. Thanks. Reading the BlueZ D-Bus GATT API description, you seem to need only basic types and arrays of basic types as properties. So I will start adding arrays of basic types. Other, more complex compound types will follow later. > For the moment, I'll only forward failing tests. Once the paperwork > is finalized I'll send you whatever suite of tests I've managed to > come up with by then. Yep, much appreciated! > Just for the record, I'm testing master currently at d08568e6e92. master HEAD is always good, since I'm committing there. I haven't the impression that we break anybody else; otherwise we would need an own branch. I would notify if needs arise. > Cheers, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-10 14:59 ` Michael Albinus @ 2020-09-10 16:57 ` Michael Albinus 2020-09-10 19:09 ` Hugh Daschbach 2020-09-10 22:53 ` Hugh Daschbach 0 siblings, 2 replies; 52+ messages in thread From: Michael Albinus @ 2020-09-10 16:57 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 [-- Attachment #1: Type: text/plain, Size: 1053 bytes --] Michael Albinus <michael.albinus@gmx.de> writes: Hi Hugh, > Reading the BlueZ D-Bus GATT API description, you seem to need only > basic types and arrays of basic types as properties. So I will start > adding arrays of basic types. Other, more complex compound types will > follow later. I have pushed my recent work to master. dbus-register-property, dbus-get-property, dbus-get-all-properties and dbus-get-all-managed-objects shall work now for your byte array. dbus-set-property will follow tomorrow, as well as other compound types but array. >> For the moment, I'll only forward failing tests. Once the paperwork >> is finalized I'll send you whatever suite of tests I've managed to >> come up with by then. > > Yep, much appreciated! I had to modify your test a little bit, see appended. It passes now for me. I have renamed it also to dbus-test05-register-property-types, so we have all property tests under test05, which makes it more easy to select these tests in batch. Does it work for you? >> Cheers, >> Hugh Best regards, Michael. [-- Attachment #2: Type: text/plain, Size: 1523 bytes --] (ert-deftest dbus-test05-register-property-types () "Check property type preservation for an own service." (skip-unless dbus--test-enabled-session-bus) (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) (unwind-protect (let ((byte-array "ByteArray")) (should (equal (dbus-register-property :session dbus--test-service dbus--test-path dbus--test-interface byte-array :read '(:array :byte 1 :byte 2 :byte 3)) `((:property :session ,dbus--test-interface ,byte-array) (,dbus--test-service ,dbus--test-path)))) (should (equal (dbus-get-property :session dbus--test-service dbus--test-path dbus--test-interface byte-array) '(1 2 3))) ;; A test for `dbus-get-property' shall be added. (let ((result (dbus-get-all-properties :session dbus--test-service dbus--test-path dbus--test-interface))) (should (equal (cdr (assoc byte-array result)) '(1 2 3)))) (let ((result (dbus-get-all-managed-objects :session dbus--test-service "/")) result1) (should (setq result1 (cadr (assoc dbus--test-path result)))) (should (setq result1 (cadr (assoc dbus--test-interface result1)))) (should (equal (cdr (assoc byte-array result1)) '(1 2 3))))) ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-10 16:57 ` Michael Albinus @ 2020-09-10 19:09 ` Hugh Daschbach 2020-09-11 8:46 ` Michael Albinus 2020-09-10 22:53 ` Hugh Daschbach 1 sibling, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-10 19:09 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: > Michael Albinus <michael.albinus@gmx.de> writes: > > I had to modify your test a little bit, see appended. It passes > now for > me. I have renamed it also to > dbus-test05-register-property-types, so we > have all property tests under test05, which makes it more easy > to select > these tests in batch. Good. I've not yet developed a good TDD perspective. So I'm likely to trip over naming and test structure conventions. I'll learn as we go. Thanks for the feedback. > Does it work for you? It does. I've added a string array test without issue. I'll add a few more and let you know if/when I come across another failure. Many thanks. Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-10 19:09 ` Hugh Daschbach @ 2020-09-11 8:46 ` Michael Albinus 0 siblings, 0 replies; 52+ messages in thread From: Michael Albinus @ 2020-09-11 8:46 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >> I had to modify your test a little bit, see appended. It passes now >> for me. I have renamed it also to >> dbus-test05-register-property-types, so we have all property tests >> under test05, which makes it more easy to select these tests in >> batch. > > Good. I've not yet developed a good TDD perspective. So I'm likely > to trip over naming and test structure conventions. I'll learn as we > go. Thanks for the feedback. These conventions are rather mine, since I've written dbus-tests.el :-) General conventions are not so many, see test/README. > Many thanks. > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-10 16:57 ` Michael Albinus 2020-09-10 19:09 ` Hugh Daschbach @ 2020-09-10 22:53 ` Hugh Daschbach 2020-09-11 9:57 ` Michael Albinus 2020-09-11 14:19 ` Michael Albinus 1 sibling, 2 replies; 52+ messages in thread From: Hugh Daschbach @ 2020-09-10 22:53 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 [-- Attachment #1: Type: text/plain, Size: 2042 bytes --] Michael Albinus writes: > Michael Albinus <michael.albinus@gmx.de> writes: > > Hi Hugh, > >> Reading the BlueZ D-Bus GATT API description, you seem to need >> only >> basic types and arrays of basic types as properties. So I will >> start >> adding arrays of basic types. Other, more complex compound >> types will >> follow later. That's mostly true. There is another BlueZ interface (advertising) that take a byte keyed dictionary. It isn't obvious from the documentation https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/advertising-api.txt. But the Manufacturer ID described mentioned in the ManufacturerData dictionary description is a byte value. The property table in the BlueZ source code looks like: { "ManufacturerData", "a{qv}", get_manufacturer_data, NULL, manufacturer_data_exists }, (https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/client/advertising.c#n465) It isn't clear that there's a commitment to support such a data structure. The DBus info page says "Every dictionary entry has a string as a key". > I have pushed my recent work to master. dbus-register-property, > dbus-get-property, dbus-get-all-properties and > dbus-get-all-managed-objects shall work now for your byte > array. dbus-set-property will follow tomorrow, as well as other > compound > types but array. > With your latest work, I have successful tests for byte arrays, string arrays, object arrays, boolean arrays, and string keyed dictionaries. I haven't been able to verify property signatures programatically. I have turned on dbus-debug and verified signatures reported by the message formatter. I assume introspection is in the queue. With introspection, we could extend the tests. I assume I shouldn't care about tests that fail with debug turned on. WRT byte keyed dictionaries, I've attached a failing test. I don't know if you want to look at it or not. Still waiting for a response from assign@gnu.org. I assume a delay of a few days is to be expected. Thanks again, Hugh [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Test DBus byte keyed dictionary property. --] [-- Type: text/x-patch, Size: 3151 bytes --] ^[[1mdiff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el^[[m ^[[1mindex a8e052efbef..c0e85449a37 100644^[[m ^[[1m--- a/test/lisp/net/dbus-tests.el^[[m ^[[1m+++ b/test/lisp/net/dbus-tests.el^[[m ^[[36m@@ -521,6 +521,56 @@^[[m ^[[mdbus-test05-register-property-several-paths^[[m ;; Cleanup.^[[m (dbus-unregister-service :session dbus--test-service)))^[[m ^[[m ^[[32m+^[[m^[[32m(ert-deftest dbus-test05-register-property-types ()^[[m ^[[32m+^[[m^[[32m "Check property type preservation for an own service."^[[m ^[[32m+^[[m^[[32m (skip-unless dbus--test-enabled-session-bus)^[[m ^[[32m+^[[m^[[32m (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))^[[m ^[[32m+^[[m ^[[32m+^[[m^[[32m (unwind-protect^[[m ^[[32m+^[[m^[[32m (let ((object-array "ByteDictionary")^[[m ^[[32m+^[[m^[[32m (expected '((8^[[m ^[[32m+^[[m^[[32m ("byte eight"))^[[m ^[[32m+^[[m^[[32m (16^[[m ^[[32m+^[[m^[[32m ("byte sixteen"))^[[m ^[[32m+^[[m^[[32m (48^[[m ^[[32m+^[[m^[[32m ((8 9 10))))))^[[m ^[[32m+^[[m^[[32m (should^[[m ^[[32m+^[[m^[[32m (equal^[[m ^[[32m+^[[m^[[32m (dbus-register-property^[[m ^[[32m+^[[m^[[32m :session dbus--test-service dbus--test-path^[[m ^[[32m+^[[m^[[32m dbus--test-interface object-array :read^[[m ^[[32m+^[[m^[[32m '(:array^[[m ^[[32m+^[[m^[[32m :dict-entry (:byte 8 (:variant :string "byte-eight"))^[[m ^[[32m+^[[m^[[32m :dict-entry (:byte 16 (:variant :object-path "/byte sixteen"))^[[m ^[[32m+^[[m^[[32m :dict-entry (:byte 48 (:variant (:array :byte 8 :byte 9 :byte 10)))))^[[m ^[[32m+^[[m^[[32m `((:property :session ,dbus--test-interface ,object-array)^[[m ^[[32m+^[[m^[[32m (,dbus--test-service ,dbus--test-path))))^[[m ^[[32m+^[[m^[[32m (should^[[m ^[[32m+^[[m^[[32m (equal^[[m ^[[32m+^[[m^[[32m (dbus-get-property^[[m ^[[32m+^[[m^[[32m :session dbus--test-service dbus--test-path^[[m ^[[32m+^[[m^[[32m dbus--test-interface object-array)^[[m ^[[32m+^[[m^[[32m expected))^[[m ^[[32m+^[[m ^[[32m+^[[m ^[[32m+^[[m^[[32m ;; A test for `dbus-get-property' shall be added.^[[m ^[[32m+^[[m ^[[32m+^[[m^[[32m (let ((result^[[m ^[[32m+^[[m^[[32m (dbus-get-all-properties^[[m ^[[32m+^[[m^[[32m :session dbus--test-service dbus--test-path^[[m ^[[32m+^[[m^[[32m dbus--test-interface)))^[[m ^[[32m+^[[m^[[32m (should (equal (cdr (assoc object-array result)) expected)))^[[m ^[[32m+^[[m ^[[32m+^[[m^[[32m (let ((result^[[m ^[[32m+^[[m^[[32m (dbus-get-all-managed-objects :session dbus--test-service "/"))^[[m ^[[32m+^[[m^[[32m result)^[[m ^[[32m+^[[m^[[32m (should (setq result1 (cadr (assoc dbus--test-path result))))^[[m ^[[32m+^[[m^[[32m (should (setq result1 (cadr (assoc dbus--test-interface result1))))^[[m ^[[32m+^[[m^[[32m (should (equal (cdr (assoc object-array result1)) expected))))^[[m ^[[32m+^[[m ^[[32m+^[[m^[[32m ;; Cleanup.^[[m ^[[32m+^[[m^[[32m (dbus-unregister-service :session dbus--test-service)))^[[m ^[[32m+^[[m (defun dbus-test-all (&optional interactive)^[[m "Run all tests for \\[dbus]."^[[m (interactive "p")^[[m ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-10 22:53 ` Hugh Daschbach @ 2020-09-11 9:57 ` Michael Albinus 2020-09-11 14:19 ` Michael Albinus 1 sibling, 0 replies; 52+ messages in thread From: Michael Albinus @ 2020-09-11 9:57 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 [-- Attachment #1: Type: text/plain, Size: 700 bytes --] Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, > WRT byte keyed dictionaries, I've attached a failing test. I don't > know if you want to look at it or not. The failing test includes some failures itself. I've fixed them (see appended), now it passes w/o any change in dbus.el. > Still waiting for a response from assign@gnu.org. I assume a delay of > a few days is to be expected. Yes, it takes time. When I ran through the process decades ago, everything was done by snail mail to and from Europe, because you have to sign legal papers physically. Now it seems to be possible to sign electronically, but I don't know how it goes these days. > Thanks again, > Hugh Best regards, Michael. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Type: text/x-patch, Size: 1871 bytes --] (ert-deftest dbus-test05-register-property-types () "Check property type preservation for an own service." (skip-unless dbus--test-enabled-session-bus) (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) (unwind-protect (let ((object-array "ByteDictionary") (expected '((8 ("byte-eight")) (16 ("/byte/sixteen")) (48 ((8 9 10)))))) (should (equal (dbus-register-property :session dbus--test-service dbus--test-path dbus--test-interface object-array :read '(:array (:dict-entry :byte 8 (:variant :string "byte-eight")) (:dict-entry :byte 16 (:variant :object-path "/byte/sixteen")) (:dict-entry :byte 48 (:variant (:array :byte 8 :byte 9 :byte 10))))) `((:property :session ,dbus--test-interface ,object-array) (,dbus--test-service ,dbus--test-path)))) (should (equal (dbus-get-property :session dbus--test-service dbus--test-path dbus--test-interface object-array) expected)) ;; A test for `dbus-get-property' shall be added. (let ((result (dbus-get-all-properties :session dbus--test-service dbus--test-path dbus--test-interface))) (should (equal (cdr (assoc object-array result)) expected))) (let ((result (dbus-get-all-managed-objects :session dbus--test-service "/")) result1) (should (setq result1 (cadr (assoc dbus--test-path result)))) (should (setq result1 (cadr (assoc dbus--test-interface result1)))) (should (equal (cdr (assoc object-array result1)) expected)))) ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-10 22:53 ` Hugh Daschbach 2020-09-11 9:57 ` Michael Albinus @ 2020-09-11 14:19 ` Michael Albinus 2020-09-15 4:05 ` Hugh Daschbach 1 sibling, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-11 14:19 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >>> Reading the BlueZ D-Bus GATT API description, you seem to need only >>> basic types and arrays of basic types as properties. So I will start >>> adding arrays of basic types. Other, more complex compound types >>> will follow later. > > That's mostly true. There is another BlueZ interface (advertising) > that take a byte keyed dictionary. It isn't obvious from the > documentation > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/advertising-api.txt. > But the Manufacturer ID described mentioned in the ManufacturerData > dictionary description is a byte value. > > The property table in the BlueZ source code looks like: > > { "ManufacturerData", "a{qv}", get_manufacturer_data, NULL, > manufacturer_data_exists > }, > > (https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/client/advertising.c#n465) > > It isn't clear that there's a commitment to support such a data > structure. The DBus info page says "Every dictionary entry has a > string as a key". Looks like this has been extended to "Every dictionary entry has a basic type as a key". Anyway, my today's commits shall support now all compound types for properties. > I haven't been able to verify property signatures programatically. I > have turned on dbus-debug and verified signatures reported by the > message formatter. I assume introspection is in the queue. With > introspection, we could extend the tests. I'm no more convinced that introspection is the way to go. What if there aren't introspection data? Maybe one could run two processes in parallel to the tests: --8<---------------cut here---------------start------------->8--- dbus-monitor --session "sender=org.gnu.Emacs.TestDBus" dbus-monitor --session "destination=org.gnu.Emacs.TestDBus" --8<---------------cut here---------------end--------------->8--- It shall be possible to analyze their structured output. > I assume I shouldn't care about tests that fail with debug turned on. Yes. However, dbus-debug on let's *all* dbus-error errors through, both internal errors, and the ones arriving from incoming D-Bus error messages. Sometimes, one wants to see the latter only. So I have added a defcustom dbus-show-dbus-errors which allows to pass only the incoming error messages. See the changed dbus-test05-register-property for examples. > Thanks again, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-11 14:19 ` Michael Albinus @ 2020-09-15 4:05 ` Hugh Daschbach 2020-09-16 12:47 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-15 4:05 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: >> It isn't clear that there's a commitment to support such a data >> structure. The DBus info page says "Every dictionary entry has >> a >> string as a key". > > Looks like this has been extended to "Every dictionary entry has > a > basic type as a key". > > Anyway, my today's commits shall support now all compound types > for properties. Excellent. Will try to submit tests for them. > Maybe one could run two processes in parallel to the tests: > > --8<---------------cut > here---------------start------------->8--- > dbus-monitor --session "sender=org.gnu.Emacs.TestDBus" > > dbus-monitor --session "destination=org.gnu.Emacs.TestDBus" > --8<---------------cut > here---------------end--------------->8--- > > It shall be possible to analyze their structured output. That idea has taken root. It'll take me a few days to put together reviewable code. But I've got a good start. Paperwork arrived today. Signed and submitted. I expect it'll take a bit longer before it's administratively complete. More when I have some signature analysis code for your review. It's complicated enough to deserve its own tests. Cheers, Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-15 4:05 ` Hugh Daschbach @ 2020-09-16 12:47 ` Michael Albinus 2020-09-16 22:23 ` Hugh Daschbach 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-16 12:47 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >> Anyway, my today's commits shall support now all compound types for >> properties. > > Excellent. Will try to submit tests for them. I've just finished my work on dbus-set-property. It shall also keep the type information of the registered property. Because of this, I've changed the internal structure of dbus-event; for all arguments the corresponding type information is propagated now. You might test this. Given you confirm this functionality, I believe we can close this bug report now. >> Maybe one could run two processes in parallel to the tests: >> >> --8<---------------cut here---------------start------------->8--- >> dbus-monitor --session "sender=org.gnu.Emacs.TestDBus" >> >> dbus-monitor --session "destination=org.gnu.Emacs.TestDBus" >> --8<---------------cut here---------------end--------------->8--- >> >> It shall be possible to analyze their structured output. > > That idea has taken root. It'll take me a few days to put together > reviewable code. But I've got a good start. Now that we have type information in dbus-event, I'll start next days to implement org.freedesktop.DBus.Monitoring.BecomeMonitor <https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-become-monitor>. If this succeeds, we could implement a counterpart to the dbus-monitor program in Elisp. And you would be able to access this information programmatically, including all message and signal call / return arguments and their types. Let's see. > Paperwork arrived today. Signed and submitted. I expect it'll take a > bit longer before it's administratively complete. Good. I'll check the copyright.list file next days regularly, in order to see whether your name appears. That is the indication that the legal process has finished. > More when I have some signature analysis code for your review. It's > complicated enough to deserve its own tests. Yep. But you could also wait for some few days, whether the BecomeMonitor work leads to usable results. > Cheers, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-16 12:47 ` Michael Albinus @ 2020-09-16 22:23 ` Hugh Daschbach 2020-09-17 12:58 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-16 22:23 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > > I've just finished my work on dbus-set-property. It shall also > keep the > type information of the registered property. Because of this, > I've > changed the internal structure of dbus-event; for all arguments > the > corresponding type information is propagated now. > > You might test this. Given you confirm this functionality, I > believe we > can close this bug report now. Good. I'll test and report back. >> >> That idea has taken root. It'll take me a few days to put >> together >> reviewable code. But I've got a good start. > > Now that we have type information in dbus-event, I'll start next > days to > implement org.freedesktop.DBus.Monitoring.BecomeMonitor > <https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-become-monitor>. If > this succeeds, we could implement a counterpart to the > dbus-monitor > program in Elisp. And you would be able to access this > information > programmatically, including all message and signal call / return > arguments and their types. Let's see. Excellent. I can now parse the output of dbus-monitor. But capturing asynchronous output and feeding it through an ah-hoc parser seems fragile. Capturing type data directly as a monitor is much more robust. There's quite a bit of boiler plate in the property tests. Do you have an issue with rolling that up in a macro? Does it make test failure analysis more difficult? Here's a candidate: (defmacro dbus-test05-test-property (name value expected) `(let ((byte-array ,name)) (should (equal (dbus-register-property :session dbus--test-service dbus--test-path dbus--test-interface ,name :read ,value) `((:property :session ,,dbus--test-interface ,,name) (,dbus--test-service ,,dbus--test-path)))) (should (equal (dbus-get-property :session dbus--test-service dbus--test-path dbus--test-interface ,name) ,expected)) ;; a test for `dbus-get-property' shall be added. (let ((result (dbus-get-all-properties :session dbus--test-service dbus--test-path dbus--test-interface))) (should (equal (cdr (assoc ,name result)) ,expected))) (let ((result (dbus-get-all-managed-objects :session dbus--test-service "/")) result1) (should (setq result1 (cadr (assoc dbus--test-path result)))) (should (setq result1 (cadr (assoc dbus--test-interface result1)))) (should (equal (cdr (assoc ,name result1)) ,expected))))) With the calling sequence something like: (dbus-test05-test-property "bytearray" '(:array :byte 1 :byte 2 :byte 3) '(1 2 3)) Opinion? Thanks, Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-16 22:23 ` Hugh Daschbach @ 2020-09-17 12:58 ` Michael Albinus 2020-09-17 18:42 ` Hugh Daschbach 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-17 12:58 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >> Now that we have type information in dbus-event, I'll start next >> days to >> implement org.freedesktop.DBus.Monitoring.BecomeMonitor >> <https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-become-monitor>. If >> this succeeds, we could implement a counterpart to the dbus-monitor >> program in Elisp. And you would be able to access this information >> programmatically, including all message and signal call / return >> arguments and their types. Let's see. > > Excellent. I can now parse the output of dbus-monitor. But capturing > asynchronous output and feeding it through an ah-hoc parser seems > fragile. Capturing type data directly as a monitor is much more > robust. Implementation is more complex than expected. Due to its nature, org.freedesktop.DBus.Monitoring.BecomeMonitor requires another (parallel) connection to the bus. This is not foreseen yet in dbusbind.c; will see how it could fly. What I could provide just now is an implementation which runs in *another* Emacs instance. This could be used for monitoring only, because it is another connection to the bus per definition. Are you interested to get such a partial implementation? > There's quite a bit of boiler plate in the property tests. Do you > have > an issue with rolling that up in a macro? Does it make test failure > analysis more difficult? No objection. But comments :-) > Here's a candidate: > > (defmacro dbus-test05-test-property (name value expected) > `(let ((byte-array ,name)) I wouldn't call the variable "byte-array"; it could be anything during test. Call it "property" or alike. > (should > (equal > (dbus-register-property > :session dbus--test-service dbus--test-path > dbus--test-interface ,name :read I would use access type :readwrite. We want also to test dbus-set-property. > ,value) > `((:property :session ,,dbus--test-interface ,,name) > (,dbus--test-service ,,dbus--test-path)))) What are the double commas good for? Typos? > (should > (equal > (dbus-get-property > :session dbus--test-service dbus--test-path > dbus--test-interface ,name) > ,expected)) > > ;; a test for `dbus-get-property' shall be added. That's my typo - dbus-set-property is meant. And yes, it shall also be here. So you might need macro arguments value1 expected1 value2 expected2. > (let ((result > (dbus-get-all-properties > :session dbus--test-service dbus--test-path > dbus--test-interface))) > (should (equal (cdr (assoc ,name result)) ,expected))) > > (let ((result > (dbus-get-all-managed-objects :session > dbus--test-service "/")) > result1) > (should (setq result1 (cadr (assoc dbus--test-path result)))) > (should (setq result1 (cadr (assoc dbus--test-interface > result1)))) > (should (equal (cdr (assoc ,name result1)) ,expected))))) > > With the calling sequence something like: > > (dbus-test05-test-property > "bytearray" > '(:array :byte 1 :byte 2 :byte 3) > '(1 2 3)) > > Opinion? See above. > Thanks, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-17 12:58 ` Michael Albinus @ 2020-09-17 18:42 ` Hugh Daschbach 2020-09-18 6:28 ` Hugh Daschbach 2020-09-18 9:36 ` Michael Albinus 0 siblings, 2 replies; 52+ messages in thread From: Hugh Daschbach @ 2020-09-17 18:42 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > >>> this succeeds, we could implement a counterpart to the >>> dbus-monitor >>> program in Elisp. And you would be able to access this >>> information >> >> Excellent. I can now parse the output of dbus-monitor. But >> capturing > > Implementation is more complex than expected. Due to its nature, > org.freedesktop.DBus.Monitoring.BecomeMonitor requires another > (parallel) connection to the bus. This is not foreseen yet in > dbusbind.c; > will see how it could fly. > > What I could provide just now is an implementation which runs in > *another* Emacs instance. This could be used for monitoring > only, > because it is another connection to the bus per definition. Are > you > interested to get such a partial implementation? I'm interested in whatever you want to implement. I see signature verification useful for testing rather than an exposed feature. From what I can see from looking at dbus-monitor output the correct property types are being exposed now. It seems to be working. So whatever we approach we take, the benefit is early warning of future regressions. You are a better judge of benefit of additional effort than I. A second Emacs instance seems to offer the same asynchronous output gathering issues that dbus-monitor poses. It does eliminates the ad-hoc parser. If you have a longer term goal, I'd suggest pursuing that rather than something partial that you'll want to replace later. But I have no objection to a parallel instance to gather request signatures. >> Do you have >> an issue with rolling that up in a macro? > > No objection. But comments :-) > >> (defmacro dbus-test05-test-property (name value expected) >> `(let ((byte-array ,name)) > > I wouldn't call the variable "byte-array"; it could be anything > during > test. Call it "property" or alike. Fixed >> (should >> (equal >> (dbus-register-property >> :session dbus--test-service dbus--test-path >> dbus--test-interface ,name :read > > I would use access type :readwrite. We want also to test > dbus-set-property. Yes, I've added a set property test. I'll move access to a parameter so I can do both positive and negative testing; confirm that :read prevents writes. Which raises the question, should dbus-set-property function call fail for a local property that isn't :readwrite, or should that only be prevented by incoming messages? Do we require that dbus-register-property be used to update a :read access property. >> ,value) >> `((:property :session ,,dbus--test-interface ,,name) >> (,dbus--test-service ,,dbus--test-path)))) > > What are the double commas good for? Typos? I had nested quasi-quoted expressions. I'm working to avoid that. So that was a bug. >> (should >> (equal >> (dbus-get-property >> :session dbus--test-service dbus--test-path >> dbus--test-interface ,name) >> ,expected)) >> >> ;; a test for `dbus-get-property' shall be added. > > That's my typo - dbus-set-property is meant. And yes, it shall > also be > here. So you might need macro arguments value1 expected1 value2 > expected2. I assumed as much. I just carried the comment around blindly. I've changed what I sent you to accept a list of pairs of values and expected return sexps. I use the first pair on the list for dbus-register-property, verify retrieval, then use dbus-set-property to update and verify the property from the remaining pairs. I need more testing and a cleanup pass. I'll pass along a better version when I think it's ready for review. I've started a few "should fail" tests. Cheers, Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-17 18:42 ` Hugh Daschbach @ 2020-09-18 6:28 ` Hugh Daschbach 2020-09-18 9:55 ` Michael Albinus 2020-09-18 13:42 ` Michael Albinus 2020-09-18 9:36 ` Michael Albinus 1 sibling, 2 replies; 52+ messages in thread From: Hugh Daschbach @ 2020-09-18 6:28 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 [-- Attachment #1: Type: text/plain, Size: 1518 bytes --] Hugh Daschbach writes: > Michael Albinus writes: > >> Hugh Daschbach <hugh@ccss.com> writes: >> >> Hi Hugh, >> > I need more testing and a cleanup pass. I'll pass along a > better > version when > I think it's ready for review. > > I've started a few "should fail" tests. I've made a bit of progress. I have a few tests that fail. There doesn't seem to be any type checking on property set. But have a look and see if you concur that these are real errors. I've attached a patch. In addition, I see a failure in dbus-test04-register-method: > F dbus-test04-register-method > Check method registration for an own service. > (ert-test-failed > ((should > (equal > (should-error > (dbus-call-method :session dbus--test-service > dbus--test-path dbus--test-interface method1 :timeout 10 "foo")) > `(dbus-error ... "The name is not activatable"))) > :form > (equal > (dbus-error "org.freedesktop.DBus.Error.ServiceUnknown" > "The name org.gnu.Emacs.TestDBus was not provided by any > .service files") > (dbus-error "org.freedesktop.DBus.Error.ServiceUnknown" > "The name is not activatable")) > :value nil :explanation > (list-elt 2 > (arrays-of-different-length 70 27 "The name > org.gnu.Emacs.TestDBus was not provided by any .service files" > "The name is not activatable" first-mismatch-at 9)))) > Your mileage may vary. I'm starting to run out of ideas for additional tests. Suggestions welcome. Cheers, Hugh [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Additional property tests. --] [-- Type: text/x-patch, Size: 12548 bytes --] From 722852e9e1d402742508233051951d21b02bc3c9 Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Thu, 17 Sep 2020 23:19:32 -0700 Subject: [PATCH] Property tests (ERT). Add DBus tests to validate property handling. Includes cycling register, get, set, get, GetAll, and GetManagedObjects over several property types. Add tests that should fail, like setting a property with a type different from it's type at registration time. --- test/lisp/net/dbus-tests.el | 319 ++++++++++++++++++++++++++++++++++++ 1 file changed, 319 insertions(+) diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 18c2a2ad6d2..682aaa8325a 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -755,6 +755,325 @@ dbus-test06-register-property-emits-signal ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(defun dbus-test06-make-property-test (selector name value expected) + "Generate a property test: register, set, get, getall sequence. +This is a helper function for the macro +`dbus-test06-test-property'. +The argument SELECTOR indicates whether the test should expand to +'dbus-register-property' (if SELECTOR is 'register) or +`dbus-set-property' (if SELECTOR is 'set). +The argument NAME is the property name. +The argument VALUE is the value to register or set. +The argument EXPECTED is a transformed VALUE representing the +form `dbus-get-property' should return." + +;; Since we don't expect this helper function and it's caller +;; `dbus-test06-make-property' to be used outside this file, we don't +;; bother with `eval-and-compile.' It would be appropriate to wrap +;; this with `eval-and-compile' if that expectation is misguided. + + `(progn + ,(cond + ((eq selector 'register) + `(should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface ,name :readwrite ,value) + '((:property :session ,dbus--test-interface ,name) + (,dbus--test-service ,dbus--test-path))))) + + ((eq selector 'set) + `(should + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface ,name ,value) + ,expected))) + + (t (signal 'wrong-type-argument "Selector should be 'register or 'set"))) + + (should + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface ,name) + ,expected)) + + (let ((result + (dbus-get-all-properties + :session dbus--test-service dbus--test-path + dbus--test-interface))) + (should (equal (cdr (assoc ,name result)) ,expected))) + + (let ((result + (dbus-get-all-managed-objects :session dbus--test-service "/")) + result1) + (should (setq result1 (cadr (assoc dbus--test-path result)))) + (should (setq result1 (cadr (assoc dbus--test-interface result1)))) + (should (equal (cdr (assoc ,name result1)) ,expected)))) ) + + +(defmacro dbus-test06-test-property (name value-list) + "Generate a DBus property test. +The argument NAME is a property name for the test. + +The argument VALUES is a list of pairs, where each pair +represents a value form and an expected returned value form. The +first pair in VALUES is used for `dbus-register-property'. +Subsequent pairs of the list are tested with +`dbus-set-property'." + (let ((values (gensym)) + (value (gensym)) + (expected (gensym)) + (pair (gensym)) + (first (gensym))) + (let ((values value-list)) + (append + `(progn) + (list + (dbus-test06-make-property-test + 'register + name + `',(caar values) + `',(cdar values))) + (mapcar (lambda (pair) + (dbus-test06-make-property-test + 'set + name + `',(car pair) + `',(cdr pair) + )) + (cdr values)))))) + +(defmacro with-dbus-monitor (buffer &rest body) + "Run BODY in an environment that captures `dbus-monitor' output in BUFFER." + (declare (indent defun)) + `(let ((process + (start-process "dbus-monitor" ,buffer + "dbus-monitor" + "--session" + (concat "sender=" dbus--test-service) + (concat "destination=" dbus--test-service)))) + (unwind-protect + (progn ,@body) + (sit-for 0.5) + (delete-process process)))) + +(ert-deftest dbus-test06-test-property-types () + "Check property type preservation for an own service." + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + (unwind-protect + (with-dbus-monitor "*dbus-monitor*" + (progn + (dbus-test06-test-property + "ByteArray" + (((:array :byte 1 :byte 2 :byte 3) . (1 2 3)) + ((:array :byte 4 :byte 5 :byte 6) . (4 5 6)))) + + (dbus-test06-test-property + "StringArray" + (((:array "one" "two" :string "three") . ("one" "two" "three")) + ((:array :string "four" :string "five" "six") . ("four" "five" "six")))) + + (dbus-test06-test-property + "ObjectArray" + (((:array + :object-path "/node00" + :object-path "/node01" + :object-path "/node0/node02") . + ("/node00" "/node01" "/node0/node02")) + ((:array + :object-path "/node10" + :object-path "/node11" + :object-path "/node0/node12") . + ("/node10" "/node11" "/node0/node12")))) + + (dbus-test06-test-property + "Dictionary" + (((:array + :dict-entry (:string "four" (:variant :string "value of four")) + :dict-entry ("five" (:variant :object-path "/nodex")) + :dict-entry ("six" (:variant (:array :byte 4 :byte 5 :byte 6)))) . + (("four" + ("value of four")) + ("five" + ("/nodex")) + ("six" + ((4 5 6))))) + ((:array + :dict-entry (:string "key0" (:variant (:array :byte 7 :byte 8 :byte 9))) + :dict-entry ("key1" (:variant :string "value")) + :dict-entry ("key2" (:variant :object-path "/node0/node1"))) . + (("key0" + ((7 8 9))) + ("key1" + ("value")) + ("key2" + ("/node0/node1")))))) + + (dbus-test06-test-property + "ByteDictionary" + (((:array + (:dict-entry :byte 8 (:variant :string "byte-eight")) + (:dict-entry :byte 16 (:variant :object-path "/byte/sixteen")) + (:dict-entry :byte 48 (:variant (:array :byte 8 :byte 9 :byte 10)))) . + ((8 ("byte-eight")) + (16 ("/byte/sixteen")) + (48 ((8 9 10))))))) + (dbus-test06-test-property + "Variant" + (((:variant "Variant string") . ("Variant string")) + ((:variant :byte 42) . (42)) + ((:variant :uint32 1000000) . (1000000)) + ((:variant :object-path "/variant/path") . ("/variant/path")) + ((:variant :signature "a{sa{sv}}") . ("a{sa{sv}}")) + ((:variant (:struct 42 "string" (:object-path "/structure/path") (:variant "last"))) . + ((42 "string" ("/structure/path") ("last")))))) + + ;; Test that :read prevents writes + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray" :read + '(:array "one" "two" :string "three")) + `((:property :session ,dbus--test-interface "StringArray") + (,dbus--test-service "/org/gnu/Emacs/TestDBus")))) + + (should ; Should this error instead? + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray" + '(:array "seven" "eight" :string "nine")) + nil)) + + (should-not ; Not update by dbus-set-property + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray") + '("seven" "eight" "nine"))) + + (should ; Verify property has registered value + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray") + '("one" "two" "three")))) + + ;; Test mismatched types in array + + (should ; Oddly enough, register works, but get fails + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "MixedArray" :readwrite + '(:array + :object-path "/node00" + :string "/node01" + :object-path "/node0/node02")) + `((:property :session ,dbus--test-interface "MixedArray") + (,dbus--test-service "/org/gnu/Emacs/TestDBus")))) + + (should-error + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "MixedArray") + '("/node00" "/node01" "/node0/node02"))) + + ;; Test integer overflow + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue" :readwrite + :byte 128) + `((:property :session ,dbus--test-interface "ByteValue") + (,dbus--test-service "/org/gnu/Emacs/TestDBus")))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + 128)) + + (should ; This should error or the next get should fail + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue" 1024) + 1024)) + + + (should-not ; This should fail or the preceeding set should error + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + 1024)) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + 128)) + + ;; Test set with invalid type + + (should ; No error, but the invalid type throws an error on get + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue" :boolean t) nil)) + + (should-not + (eq + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + t)) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + 128)) + + ;; Test invalid type specification + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "InvalidType" :readwrite + :keyword 128) + `((:property :session ,dbus--test-interface "InvalidType") + (,dbus--test-service "/org/gnu/Emacs/TestDBus")))) + + (should-error + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "InvalidType") + 128))) + + + ;; Cleanup. + + (message "cleanup") + (dbus-unregister-service :session dbus--test-service))) + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") -- 2.28.0 ^ permalink raw reply related [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-18 6:28 ` Hugh Daschbach @ 2020-09-18 9:55 ` Michael Albinus 2020-09-18 13:42 ` Michael Albinus 1 sibling, 0 replies; 52+ messages in thread From: Michael Albinus @ 2020-09-18 9:55 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >> I need more testing and a cleanup pass. I'll pass along a better >> version when >> I think it's ready for review. >> >> I've started a few "should fail" tests. > > I've made a bit of progress. I have a few tests that fail. There > doesn't seem to be any type checking on property set. But have a look > and see if you concur that these are real errors. I've attached a > patch. Well, before getting type information in dbus-event, it wasn't possible for dbus-property-handler to know the types of values provided by org.freedesktop.DBus.Properties.Set method calls. Therefore I've said, that the type used in dbus-register-property shall be inherited. This decision wasn't dictated by the D-Bus API, it was just an implementation restriction. Now, that the type information is preserved, I have abandoned this restriction. You can register a property with any type, and you can overwrite this property via an ofDP.Set call with a value of any other type. This is not forbidden by the D-Bus API (but highly discouraged, I guess). > In addition, I see a failure in dbus-test04-register-method: > >> (equal >> (dbus-error "org.freedesktop.DBus.Error.ServiceUnknown" "The name org.gnu.Emacs.TestDBus was not provided by any .service files") >> (dbus-error "org.freedesktop.DBus.Error.ServiceUnknown" "The name is not activatable")) Oops, yes. The intention of this check is to see, whether org.freedesktop.DBus.Error.ServiceUnknown is reported (it is). The additional explanation doesn't matter, and it seems to be different depending on the D-Bus daemon implementation (I'm using Fedora 32). So I've pushed a fix, which checks just for the D-Bus error name, w/o the additional text. > I'm starting to run out of ideas for additional tests. Suggestions > welcome. The major black hole seems to be dbus-introspect* tests. If you are interested? I fear writing them will be boring, so I haven't done them yet ... OTOH, they are not the most important part of Emacs' D-Bus implementation. > Cheers, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-18 6:28 ` Hugh Daschbach 2020-09-18 9:55 ` Michael Albinus @ 2020-09-18 13:42 ` Michael Albinus 2020-09-18 15:50 ` Michael Albinus 1 sibling, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-18 13:42 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, In general, your tests are very useful. Thanks! Just some comments on your patch. > Add tests that should fail, like setting a property with a type > different from it's type at registration time. As said the other message, this constraint doesn't exist any longer. Registered services might want to control, which properties are set. This could be the type of a property, or a restriction of the value (for example, just a predefined set of strings could be allowed). Maybe, we give these services such a mean? That is, they could add an own handler function in dbus-register-property, which is applied when a org.freedesktop.DBus.Properties.Set method call is handled. WDYT? > +(defun dbus-test06-make-property-test (selector name value expected) I would call it dbus--test-make-property-test. test06 isn't important, and the double slash "--" is an indication that this is an internal function, which shouldn't leave the dbus-tests.el scope. See the other helper functions in the file. > +;; Since we don't expect this helper function and it's caller > +;; `dbus-test06-make-property' to be used outside this file, we don't > +;; bother with `eval-and-compile.' It would be appropriate to wrap > +;; this with `eval-and-compile' if that expectation is misguided. Well, it is uncommon that a function returns a code snippet. I haven't checked, but couldn't you achieve your goal by changing this defun into a defsubst? > +(defmacro dbus-test06-test-property (name value-list) Same comment on name here. I would call it dbus--test-property. > +The argument VALUES is a list of pairs, where each pair > +represents a value form and an expected returned value form. The > +first pair in VALUES is used for `dbus-register-property'. > +Subsequent pairs of the list are tested with > +`dbus-set-property'." The second argument is VALUE-LIST, not VALUES. However, Elisp encourages an argument list like (defmacro dbus-test-test-property (name &rest value-list) This simplifies call conventions, you can call then with several key-value arguments like (dbus--test-property "ByteArray" '((:array :byte 1 :byte 2 :byte 3) . (1 2 3)) '((:array :byte 4 :byte 5 :byte 6) . (4 5 6))) > +(defmacro with-dbus-monitor (buffer &rest body) Such a macro name would poison your Elisp name space. Keep the dbus--test prefix, and name the macro like dbus--test-with-dbus-monitor. > + (unwind-protect > + (progn ,@body) > + (sit-for 0.5) sit-for is problematic, because it would delay the test run by 0.5 seconds, unconditionally. People regard this negative, because the (whole) Emacs test suite shall run fast. A better check might be (with-timeout (1 (dbus--test-timeout-handler)) (while (accept-process-output process 0 nil t))) > + (should > + (equal > + (dbus-register-property > + :session dbus--test-service dbus--test-path > + dbus--test-interface "StringArray" :read > + '(:array "one" "two" :string "three")) > + `((:property :session ,dbus--test-interface "StringArray") > + (,dbus--test-service "/org/gnu/Emacs/TestDBus")))) You might use ,dbus--test-path instead. Here and everywhere else. > + > + (should ; Should this error instead? > + (equal > + (dbus-set-property > + :session dbus--test-service dbus--test-path > + dbus--test-interface "StringArray" > + '(:array "seven" "eight" :string "nine")) > + nil)) Good question. dbus-set-property and dbus-get-property do not propagate D-Bus errors. Maybe we shall change the functions to do so? I've asked this already myself. > + ;; Test mismatched types in array > + > + (should ; Oddly enough, register works, but get fails > + (equal > + (dbus-register-property > + :session dbus--test-service dbus--test-path > + dbus--test-interface "MixedArray" :readwrite > + '(:array > + :object-path "/node00" > + :string "/node01" > + :object-path "/node0/node02")) > + `((:property :session ,dbus--test-interface "MixedArray") > + (,dbus--test-service "/org/gnu/Emacs/TestDBus")))) Hmm, yes. dbus-register-property does not perform a local type check. And honestly, I don't want to do it; I let the D-Bus daemon do the job. > + (should-error > + (equal > + (dbus-get-property > + :session dbus--test-service dbus--test-path > + dbus--test-interface "MixedArray") > + '("/node00" "/node01" "/node0/node02"))) Yes, dbus-get-property is hit by the mismatched types in the :array. Isn't this sufficient? > + (should ; This should error or the next get should fail > + (equal > + (dbus-set-property > + :session dbus--test-service dbus--test-path > + dbus--test-interface "ByteValue" 1024) > + 1024)) No error expected. You haven't given 1024 a type (like :byte), so it is handled as :uint32. > + ;; Test invalid type specification > + > + (should > + (equal > + (dbus-register-property > + :session dbus--test-service dbus--test-path > + dbus--test-interface "InvalidType" :readwrite > + :keyword 128) > + `((:property :session ,dbus--test-interface "InvalidType") > + (,dbus--test-service "/org/gnu/Emacs/TestDBus")))) Oops. This shall be detected in dbus-register-property. > Cheers, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-18 13:42 ` Michael Albinus @ 2020-09-18 15:50 ` Michael Albinus 0 siblings, 0 replies; 52+ messages in thread From: Michael Albinus @ 2020-09-18 15:50 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Michael Albinus <michael.albinus@gmx.de> writes: Hi Hugh, >> + (should ; This should error or the next get should fail >> + (equal >> + (dbus-set-property >> + :session dbus--test-service dbus--test-path >> + dbus--test-interface "ByteValue" 1024) >> + 1024)) > > No error expected. You haven't given 1024 a type (like :byte), so it is > handled as :uint32. And even if you would have prefixed the value with :byte, there won't be an error. In dbusbind.c, byte values are simply computed by taking the modulo 255: unsigned char val = XFIXNAT (object) & 0xFF; ":byte 1024" is equal to ":byte 4". Similar conversions happen for the other basic types, based on numbers. Maybe we could add some tests for these conversions? Since they are not restricted to property handling, (a) new test(s) dbus-test01-* would help. >> Cheers, >> Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-17 18:42 ` Hugh Daschbach 2020-09-18 6:28 ` Hugh Daschbach @ 2020-09-18 9:36 ` Michael Albinus 2020-09-19 3:32 ` Hugh Daschbach 1 sibling, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-18 9:36 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >> Implementation is more complex than expected. Due to its nature, >> org.freedesktop.DBus.Monitoring.BecomeMonitor requires another >> (parallel) connection to the bus. This is not foreseen yet in >> dbusbind.c; >> will see how it could fly. >> >> What I could provide just now is an implementation which runs in >> *another* Emacs instance. This could be used for monitoring only, >> because it is another connection to the bus per definition. Are you >> interested to get such a partial implementation? > > I'm interested in whatever you want to implement. I see signature > verification useful for testing rather than an exposed feature. > > From what I can see from looking at dbus-monitor output the correct > property types are being exposed now. It seems to be working. > > So whatever we approach we take, the benefit is early warning of > future > regressions. You are a better judge of benefit of additional effort > than I. > > A second Emacs instance seems to offer the same asynchronous output > gathering issues that dbus-monitor poses. It does eliminates the > ad-hoc > parser. > > If you have a longer term goal, I'd suggest pursuing that rather than > something partial that you'll want to replace later. > > But I have no objection to a parallel instance to gather request > signatures. I don't know where we end up. I'm still poking around how to implement a second connection to the same bus. If it is not too expensive to implement I'd prefer this. > Which raises the question, should dbus-set-property function call fail > for a local property that isn't :readwrite, or should that only be > prevented by incoming messages? dbus-set-property doesn't know, whether a property is registered locally. I guess an error reply is reasonable, whether the property is registered locally, or not. > Do we require that dbus-register-property be used to update a :read > access property. dbus-set-property shall fail when the property has :read access. Yes, such a property can be changed only by dbus-register-property. But :read access is intended to tell the clients, that they shouldn't change the property; an error in dbus-set-property (returning nil, respectively) is appropriate. > Cheers, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-18 9:36 ` Michael Albinus @ 2020-09-19 3:32 ` Hugh Daschbach 2020-09-20 15:05 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-19 3:32 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, >> There doesn't seem to be any type checking on property set. > > Well, before getting type information in dbus-event, it wasn't > possible > for dbus-property-handler to know the types of values provided > by > org.freedesktop.DBus.Properties.Set method calls. Therefore I've > said, > that the type used in dbus-register-property shall be > inherited. This > decision wasn't dictated by the D-Bus API, it was just an > implementation > restriction. > > Now, that the type information is preserved, I have abandoned > this > restriction. You can register a property with any type, and you > can > overwrite this property via an ofDP.Set call with a value of any > other > type. This is not forbidden by the D-Bus API (but highly > discouraged, I > guess). Makes sense. I'll adjust tests accordingly. >> I'm starting to run out of ideas for additional >> tests. Suggestions >> welcome. > > The major black hole seems to be dbus-introspect* tests. If you > are > interested? I fear writing them will be boring, so I haven't > done them > yet ... > > OTOH, they are not the most important part of Emacs' D-Bus > implementation. I'm willing. Will have a look. >> +(defun dbus-test06-make-property-test (selector name value >> expected) > > I would call it dbus--test-make-property-test. test06 isn't > important, > and the double slash "--" is an indication that this is an > internal > function, which shouldn't leave the dbus-tests.el scope. See the > other > helper functions in the file. Good by me. I'll rename accordingly. >> +;; Since we don't expect this helper function and it's caller >> +;; `dbus-test06-make-property' to be used outside this file, >> we don't >> +;; bother with `eval-and-compile.' It would be appropriate to >> wrap >> +;; this with `eval-and-compile' if that expectation is >> misguided. > > Well, it is uncommon that a function returns a code snippet. I > haven't > checked, but couldn't you achieve your goal by changing this > defun into > a defsubst? Seems like a better approach. I'm new enough at this that I wasn't aware of defsubst. I'll give it a go, thanks. >> +(defmacro dbus-test06-test-property (name value-list) > > Same comment on name here. I would call it dbus--test-property. > >> +The argument VALUES is a list of pairs, where each pair >> +represents a value form and an expected returned value form. >> The >> +first pair in VALUES is used for `dbus-register-property'. >> +Subsequent pairs of the list are tested with >> +`dbus-set-property'." > > The second argument is VALUE-LIST, not VALUES. However, Elisp > encourages > an argument list like > > (defmacro dbus-test-test-property (name &rest value-list) > > This simplifies call conventions, you can call then with several > key-value arguments like > > (dbus--test-property > "ByteArray" > '((:array :byte 1 :byte 2 :byte 3) . (1 2 3)) > '((:array :byte 4 :byte 5 :byte 6) . (4 5 6))) > >> +(defmacro with-dbus-monitor (buffer &rest body) Excellent feedback. Changes incorporated. > Such a macro name would poison your Elisp name space. Keep the > dbus--test prefix, and name the macro like > dbus--test-with-dbus-monitor. > >> + (unwind-protect >> + (progn ,@body) >> + (sit-for 0.5) > > sit-for is problematic, because it would delay the test run by > 0.5 > seconds, unconditionally. People regard this negative, because > the > (whole) Emacs test suite shall run fast. A better check might be > > (with-timeout (1 (dbus--test-timeout-handler)) > (while (accept-process-output process 0 nil t))) Thanks. I knew the sit-for was a hack, worse an unpredictable hack. I should have mentioned that I planned to remove the dbus-monitor wrapper when before final submission. It's useful for debugging the tests. But the tests themselves don't need this. I've folded in your suggestion, but it's scheduled for the chopping block, anyway. I'm still learning. Your feedback is most helpful. Thanks. >> + (should >> + (equal >> + (dbus-register-property >> + :session dbus--test-service dbus--test-path >> + dbus--test-interface "StringArray" :read >> + '(:array "one" "two" :string "three")) >> + `((:property :session ,dbus--test-interface >> "StringArray") >> + (,dbus--test-service "/org/gnu/Emacs/TestDBus")))) > > You might use ,dbus--test-path instead. Here and everywhere > else. Good catch. Thanks. >> + >> + (should ; Should this >> error instead? >> + (equal >> + (dbus-set-property >> ... >> + '(:array "seven" "eight" :string "nine")) > > Good question. dbus-set-property and dbus-get-property do not > propagate > D-Bus errors. Maybe we shall change the functions to do so? I've > asked > this already myself. I don't have a strong opinion either way. I'm just trying to note corner cases. >> + ;; Test mismatched types in array >> + >> + (should ; Oddly enough, >> register works, but get fails >> + (equal > > Hmm, yes. dbus-register-property does not perform a local type > check. And honestly, I don't want to do it; I let the D-Bus > daemon do > the job. Great. >> + dbus--test-interface "MixedArray") >> + '("/node00" "/node01" "/node0/node02"))) > > Yes, dbus-get-property is hit by the mismatched types in the > :array. Isn't > this sufficient? It is. As long as we can predict where errors will be reported. I'll update comments to indicate intended behavior. >> + (should ; This should >> error or the next get should fail >> + (equal >> + (dbus-set-property >> + :session dbus--test-service dbus--test-path >> + dbus--test-interface "ByteValue" 1024) >> + 1024)) > > No error expected. You haven't given 1024 a type (like :byte), > so it is > handled as :uint32. Cool. With the explanation regarding dbus-set-property changing types, this makes perfect sense. > And even if you would have prefixed the value with :byte, there > won't be > an error. In dbusbind.c, byte values are simply computed by > taking the > modulo 255: > > unsigned char val = XFIXNAT (object) & 0xFF; > > ":byte 1024" is equal to ":byte 4". Similar conversions happen > for the > other basic types, based on numbers. Good. I haven't thought deeply enough about DBus to anticipate truncation. I've added a test for this, an extract of which is below. The get returns nil instead of 4. I can change the expected value, but wanted to run this by you first. > Maybe we could add some tests for these conversions? Since they > are not > restricted to property handling, (a) new test(s) dbus-test01-* > would help. I'll have a look. >>> Implementation is more complex than expected. Due to its >>> nature, >> But I have no objection to a parallel instance to gather >> request >> signatures. > > I don't know where we end up. I'm still poking around how to > implement a > second connection to the same bus. If it is not too expensive to > implement I'd prefer this. Fair enough. Your call. >> Which raises the question, should dbus-set-property function >> call fail >> for a local property that isn't :readwrite, or should that only >> be >> prevented by incoming messages? > > dbus-set-property doesn't know, whether a property is registered > locally. I guess an error reply is reasonable, whether the > property is > registered locally, or not. Would be nice. Unless it adds overhead, like an introspection. >> Do we require that dbus-register-property be used to update a >> :read >> access property. > > dbus-set-property shall fail when the property has :read > access. Yes, > such a property can be changed only by > dbus-register-property. But :read > access is intended to tell the clients, that they shouldn't > change the > property; an error in dbus-set-property (returning nil, > respectively) is > appropriate. Cool. I mentioned an additional test above. The get below, extracted from the larger test, returns nil instead of 4: (ert-deftest dbus-test-ad-hoc () (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) (dbus-register-service :session dbus--test-service) (should ; Test value truncation (equal (dbus-register-property :session dbus--test-service dbus--test-path dbus--test-interface "ByteValue" :read :byte 1024) `((:property :session ,dbus--test-interface "ByteValue") (,dbus--test-service ,dbus--test-path)))) (should ; Returns 0 instead of 4. (equal (dbus-get-property :session dbus--test-service dbus--test-path dbus--test-interface "ByteValue") 4)) (dbus-unregister-service :session dbus--test-service)) Should I update the expectation to zero? > Best regards, Michael. Cheers, Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-19 3:32 ` Hugh Daschbach @ 2020-09-20 15:05 ` Michael Albinus 2020-09-21 11:50 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-20 15:05 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >>> + >>> + (should ; Should this error >>> instead? >>> + (equal >>> + (dbus-set-property >>> ... >>> + '(:array "seven" "eight" :string "nine")) >> >> Good question. dbus-set-property and dbus-get-property do not >> propagate >> D-Bus errors. Maybe we shall change the functions to do so? I've >> asked >> this already myself. > > I don't have a strong opinion either way. I'm just trying to note > corner cases. Well, I have adapted dbus-set-property and dbus-get-property to propagate the errors. >>> + ;; Test mismatched types in array >>> + >>> + (should ; Oddly enough, register >>> works, but get fails >>> + (equal >> >> Hmm, yes. dbus-register-property does not perform a local type >> check. And honestly, I don't want to do it; I let the D-Bus daemon >> do >> the job. > > Great. Should be checked now. When dbus-register-property is called, it applies internally a dbus-set-property or dbus-get-property now. As side effect, the value is checked by the D-Bus daemon, and you shall see errors. >> And even if you would have prefixed the value with :byte, there >> won't be >> an error. In dbusbind.c, byte values are simply computed by taking >> the >> modulo 255: >> >> unsigned char val = XFIXNAT (object) & 0xFF; >> >> ":byte 1024" is equal to ":byte 4". Similar conversions happen for >> the >> other basic types, based on numbers. > > Good. I haven't thought deeply enough about DBus to anticipate > truncation. I've added a test for this, an extract of which is below. > The get returns nil instead of 4. I can change the expected value, > but > wanted to run this by you first. Of course I'm wrong, ":byte 1024" shall be the same as "byte 0". > (ert-deftest dbus-test-ad-hoc () > (dbus-ignore-errors (dbus-unregister-service :session > dbus--test-service)) > (dbus-register-service :session dbus--test-service) > (should ; Test value truncation > (equal > (dbus-register-property > :session dbus--test-service dbus--test-path > dbus--test-interface "ByteValue" :read :byte 1024) > `((:property :session ,dbus--test-interface "ByteValue") > (,dbus--test-service ,dbus--test-path)))) > > (should ; Returns 0 instead of 4. > (equal > (dbus-get-property > :session dbus--test-service dbus--test-path > dbus--test-interface "ByteValue") > 4)) Of course 0. As said, I was wrong. > (dbus-unregister-service :session dbus--test-service)) > > Should I update the expectation to zero? Yes, please. > Cheers, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-20 15:05 ` Michael Albinus @ 2020-09-21 11:50 ` Michael Albinus 2020-09-22 3:48 ` Hugh Daschbach 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-21 11:50 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hi Hugh, just FTR, I have added test cases dbus-test01-basic-types and dbus-test01-compound-types. They use the recently added function dbus-check-arguments, which generates a new D-Bus message, but without sending it. As side effect, we get errors from dbusbind.c in case of. Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-21 11:50 ` Michael Albinus @ 2020-09-22 3:48 ` Hugh Daschbach 2020-09-22 16:09 ` Michael Albinus 2020-09-22 17:36 ` Michael Albinus 0 siblings, 2 replies; 52+ messages in thread From: Hugh Daschbach @ 2020-09-22 3:48 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 [-- Attachment #1: Type: text/plain, Size: 943 bytes --] Michael Albinus writes: > Hi Hugh, > > just FTR, I have added test cases dbus-test01-basic-types and > dbus-test01-compound-types. They use the recently added function > dbus-check-arguments, which generates a new D-Bus message, but > without > sending it. As side effect, we get errors from dbusbind.c in > case of. > > Best regards, Michael. Thanks for the heads up. I noticed the error messages. Happy to ignore them. I have attached two patches for your review. I think the property tests are complete; I've adjusted the tests to expect errors on register or set rather than get. The other patch is my first draft for testing introspection. I could dig deeper into the dbus-introspect-get-interface, but wanted to come up for air first. Let me know if you think it's worth the effort given the individual method, signal, and property tests. And, of course, let me know what you think should be reworked. Thanks, Hugh [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Candidate patch for additional property tests. --] [-- Type: text/x-patch, Size: 10309 bytes --] From f3f1f07d94676a22842b04a050231639edf2ec29 Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Thu, 17 Sep 2020 23:19:32 -0700 Subject: [PATCH 1/2] Property tests (ERT). Add DBus tests to validate property handling. Includes cycling register, get, set, get, GetAll, and GetManagedObjects over several property types. Add tests that should fail, like setting a property with a type different from it's type at registration time. --- test/lisp/net/dbus-tests.el | 271 ++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 62ed3f2bfb4..993a2e3848a 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -1004,6 +1004,277 @@ dbus-test06-register-property-emits-signal ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(defsubst dbus--test-run-property-test (selector name value expected) + "Generate a property test: register, set, get, getall sequence. +This is a helper function for the macro `dbus--test-property'. +The argument SELECTOR indicates whether the test should expand to +'dbus-register-property' (if SELECTOR is 'register) or +`dbus-set-property' (if SELECTOR is 'set). +The argument NAME is the property name. +The argument VALUE is the value to register or set. +The argument EXPECTED is a transformed VALUE representing the +form `dbus-get-property' should return." + (cond + ((eq selector 'register) + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface name :readwrite value) + `((:property :session ,dbus--test-interface ,name) + (,dbus--test-service ,dbus--test-path))))) + + ((eq selector 'set) + (should + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface name value) + expected))) + + (t (signal 'wrong-type-argument "Selector should be 'register or 'set."))) + + (should + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface name) + expected)) + + (let ((result + (dbus-get-all-properties + :session dbus--test-service dbus--test-path + dbus--test-interface))) + (should (equal (cdr (assoc name result)) expected))) + + (let ((result + (dbus-get-all-managed-objects :session dbus--test-service "/")) + result1) + (should (setq result1 (cadr (assoc dbus--test-path result)))) + (should (setq result1 (cadr (assoc dbus--test-interface result1)))) + (should (equal (cdr (assoc name result1)) expected)))) + + +(defsubst dbus--test-property (name &rest value-list) + "Test a DBus property named by string argument NAME. + +The argument VALUE-LIST is a sequence of pairs, where each pair +represents a value form and an expected returned value form. The +first pair in VALUES is used for `dbus-register-property'. +Subsequent pairs of the list are tested with +`dbus-set-property'." + (let ((values (car value-list))) + (dbus--test-run-property-test + 'register + name + (car values) + (cdr values))) + (dolist (values (cdr value-list)) + (dbus--test-run-property-test + 'set + name + (car values) + (cdr values)))) + +(ert-deftest dbus-test06-test-property-types () + "Check property access and mutation for an own service." + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + (unwind-protect + (progn + (dbus--test-property + "ByteArray" + '((:array :byte 1 :byte 2 :byte 3) . (1 2 3)) + '((:array :byte 4 :byte 5 :byte 6) . (4 5 6))) + + (dbus--test-property + "StringArray" + '((:array "one" "two" :string "three") . ("one" "two" "three")) + '((:array :string "four" :string "five" "six") . ("four" "five" "six"))) + + (dbus--test-property + "ObjectArray" + '((:array + :object-path "/node00" + :object-path "/node01" + :object-path "/node0/node02") . + ("/node00" "/node01" "/node0/node02")) + '((:array + :object-path "/node10" + :object-path "/node11" + :object-path "/node0/node12") . + ("/node10" "/node11" "/node0/node12"))) + + (dbus--test-property + "Dictionary" + '((:array + :dict-entry (:string "four" (:variant :string "value of four")) + :dict-entry ("five" (:variant :object-path "/nodex")) + :dict-entry ("six" (:variant (:array :byte 4 :byte 5 :byte 6)))) . + (("four" + ("value of four")) + ("five" + ("/nodex")) + ("six" + ((4 5 6))))) + '((:array + :dict-entry (:string "key0" (:variant (:array :byte 7 :byte 8 :byte 9))) + :dict-entry ("key1" (:variant :string "value")) + :dict-entry ("key2" (:variant :object-path "/node0/node1"))) . + (("key0" + ((7 8 9))) + ("key1" + ("value")) + ("key2" + ("/node0/node1"))))) + + (dbus--test-property + "ByteDictionary" + '((:array + (:dict-entry :byte 8 (:variant :string "byte-eight")) + (:dict-entry :byte 16 (:variant :object-path "/byte/sixteen")) + (:dict-entry :byte 48 (:variant (:array :byte 8 :byte 9 :byte 10)))) . + ((8 ("byte-eight")) + (16 ("/byte/sixteen")) + (48 ((8 9 10)))))) + + (dbus--test-property + "Variant" + '((:variant "Variant string") . ("Variant string")) + '((:variant :byte 42) . (42)) + '((:variant :uint32 1000000) . (1000000)) + '((:variant :object-path "/variant/path") . ("/variant/path")) + '((:variant :signature "a{sa{sv}}") . ("a{sa{sv}}")) + '((:variant (:struct 42 "string" (:object-path "/structure/path") (:variant "last"))) . + ((42 "string" ("/structure/path") ("last"))))) + + ;; Test that :read prevents writes + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray" :read + '(:array "one" "two" :string "three")) + `((:property :session ,dbus--test-interface "StringArray") + (,dbus--test-service ,dbus--test-path)))) + + (should-error ; Cannot set property with :read access + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray" + '(:array "seven" "eight" :string "nine")) + nil)) + + (should-not + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray") + '("seven" "eight" "nine"))) + + (should ; Verify property has registered value + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray") + '("one" "two" "three"))) + + ;; Test mismatched types in array + + (should-error + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "MixedArray" :readwrite + '(:array + :object-path "/node00" + :string "/node01" + :object-path "/node0/node02")) + `((:property :session ,dbus--test-interface "MixedArray") + (,dbus--test-service ,dbus--test-path)))) + + ;; Test integer overflow + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue" :readwrite + :byte 128) + `((:property :session ,dbus--test-interface "ByteValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + 128)) + + (should ; dbus-set-property may change property type + (= + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue" 1024) + 1024)) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + 1024)) + + (should + (= + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue" :byte 520) + 8)) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + 8)) + + (should ; Another change property type + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue" :boolean t) + t)) + + (should + (eq + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + t)) + + ;; Test invalid type specification + + (should-error + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "InvalidType" :readwrite + :keyword 128) + `((:property :session ,dbus--test-interface "InvalidType") + (,dbus--test-service ,dbus--test-path))))) + + + ;; Cleanup. + + + (message "cleanup") + (dbus-unregister-service :session dbus--test-service))) + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") -- 2.28.0 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #3: First cut approximation of Introspection tests. --] [-- Type: text/x-patch, Size: 14700 bytes --] From 41ad18f0094740220d5df62c656dc09cf4c18c97 Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Mon, 21 Sep 2020 17:12:49 -0700 Subject: [PATCH 2/2] Draft introspection tests. Define an Introspection interface. Then use dbus-introspect-* methods to examine and verify the elements of the interface. --- test/lisp/net/dbus-tests.el | 362 ++++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 993a2e3848a..e047dcc5fae 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -1275,6 +1275,368 @@ dbus-test06-test-property-types (message "cleanup") (dbus-unregister-service :session dbus--test-service))) +(defun dbus--test-introspect () + "Return test introspection string." + "<?xml version=\"1.0\"?> +<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\"> +<node> + <interface name=\"org.freedesktop.DBus.Introspectable\"> + <method name=\"Introspect\"> + <arg name=\"xml\" type=\"s\" direction=\"out\"/> + </method> + </interface> + <interface name=\"org.freedesktop.DBus.Properties\"> + <method name=\"Get\"> + <arg name=\"interface\" type=\"s\" direction=\"in\"/> + <arg name=\"name\" type=\"s\" direction=\"in\"/> + <arg name=\"value\" type=\"v\" direction=\"out\"/> + </method> + <method name=\"Set\"> + <arg name=\"interface\" type=\"s\" direction=\"in\"/> + <arg name=\"name\" type=\"s\" direction=\"in\"/> + <arg name=\"value\" type=\"v\" direction=\"in\"/> + </method> + <method name=\"GetAll\"> + <arg name=\"interface\" type=\"s\" direction=\"in\"/> + <arg name=\"properties\" type=\"a{sv}\" direction=\"out\"/> + </method> + <signal name=\"PropertiesChanged\"> + <arg name=\"interface\" type=\"s\"/> + <arg name=\"changed_properties\" type=\"a{sv}\"/> + <arg name=\"invalidated_properties\" type=\"as\"/> + </signal> + </interface> + <interface name=\"org.gnu.Emacs.TestDBus.Interface\"> + <method name=\"Connect\"> + <arg name=\"uuid\" type=\"s\" direction=\"in\"/> + <arg name=\"mode\" type=\"y\" direction=\"in\"/> + <arg name=\"options\" type=\"a{sv}\" direction=\"in\"/> + <arg name=\"interface\" type=\"s\" direction=\"out\"/> + </method> + <method name=\"DeprecatedMethod0\"> + <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/> + </method> + <method name=\"DeprecatedMethod1\"> + <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/> + </method> + <property name=\"Connected\" type=\"b\" access=\"read\"/> + <property name=\"Player\" type=\"o\" access=\"read\"/> + <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/> + </interface> + <node name=\"node0\"/> + <node name=\"node1\"/> +</node> +") + +(defsubst dbus--test-examine-interface (iface-name + expected-properties + expected-methods + expected-signals + expected-annotations) + "Validate an interface definition for `dbus-test-07-test-introspection'. +The argument IFACE-NAME is a string naming the interface to validate. +The arguments EXPECTED-PROPERTIES, EXPECTED-METHODS, EXPECTED-SIGNALS, and +EXPECTED-ANNOTATIONS represent the names of the interface's properties, +methods, signals, and annotations, respecively." + + (let ((interface (dbus-introspect-get-interface + :session + dbus--test-service + dbus--test-path + iface-name))) + (pcase-let ((`(interface ((name . ,name)) . ,rest) interface)) + (should + (string-equal name iface-name)) + (should + (string-equal name (dbus-introspect-get-attribute interface "name"))) + + (let (properties methods signals annotations) + (mapc (lambda (x) + (let ((name (dbus-introspect-get-attribute x "name"))) + (cond + ((eq 'property (car x)) (push name properties)) + ((eq 'method (car x)) (push name methods)) + ((eq 'signal (car x)) (push name signals)) + ((eq 'annotation (car x)) (push name annotations))))) + rest) + + (should + (equal + (nreverse properties) + expected-properties)) + (should + (equal + (nreverse methods) + expected-methods)) + (should + (equal + (nreverse signals) + expected-signals)) + (should + (equal + (nreverse annotations) + expected-annotations))))) + ;; should we examine method and signal arguments here as well? + ;; or is it sufficient to test arguments from dbus-introspect-get-(method|signal)? + ) + +(defsubst dbus--test-validate-annotations (annotations expected-annotations) + "Validate a list of DBus ANNOTATIONS. +Ensure each string in EXPECTED-ANNOTATIONS names an element of ANNOTATIONS. +And ensure each ANNOTATIONS has a value attribute marked \"true\"." + (mapc + (lambda (annotation) + (let ((name (dbus-introspect-get-attribute annotation "name")) + (value (dbus-introspect-get-attribute annotation "value"))) + (should + (member name expected-annotations)) + (should + (equal value "true")))) + annotations)) + +(defsubst dbus--test-examine-property (interface + property-name + expected-annotations + &rest expected-args) + "Validate a property definition for `dbus-test-07-test-introspection'. + +The argument INTERFACE is a string naming the interface owning PROPERTY-NAME. +The argument PROPERTY-NAME is a string naming the property to validate. +The arguments EXPECTED-ANNOTATIONS represent the names of the property's properties. +The argument EXPECTED-ARGS is a list of expected arguments for the property." + (let* ((property (dbus-introspect-get-property + :session + dbus--test-service + dbus--test-path + interface + property-name)) + (name (dbus-introspect-get-attribute property "name")) + (type (dbus-introspect-get-attribute property "type")) + (access (dbus-introspect-get-attribute property "access")) + (expected (assoc-string name expected-args))) + (should-not (equal expected nil)) + + (should + (string-equal name property-name)) + + (should + (string-equal + (nth 0 expected) + name)) + + (should + (string-equal + (nth 1 expected) + type)) + + (should + (string-equal + (nth 2 expected) + access)))) + +(defsubst dbus--test-validate-m-or-s (tree expected-annotations expected-args) + "Validate a method or signal definition for `dbus-test-07-test-introspection'. +The argument TREE is an sexp returned from either `dbus-introspect-get-method' +or `dbus-introspect-get-signal' +The arguments EXPECTED-ANNOTATIONS is an sexp matching the annotations defined +for the method or signal. +The argument EXPECTED-ARGS is a list of expected arguments for +the method or signal." + (let (args annotations) + (mapc (lambda (elem) + (let ((name (dbus-introspect-get-attribute elem "name"))) + (cond + ((eq 'arg (car elem)) (push elem args)) + ((eq 'annotation (car elem)) (push elem annotations))))) + tree) + (should + (equal + (nreverse args) + expected-args)) + (dbus--test-validate-annotations annotations expected-annotations))) + +(defsubst dbus--test-examine-signal (interface + signal-name + expected-annotations + &rest expected-args) + "Validate a signal definition for `dbus-test-07-test-introspection'. + +The argument INTERFACE is a string naming the interface owning SIGNAL-NAME. +The argument SIGNAL-NAME is a string naming the signal to validate. +The arguments EXPECTED-ANNOTATIONS represent the names of the signal's properties. +The argument EXPECTED-ARGS is a list of expected arguments for the signal." + (let ((signal (dbus-introspect-get-signal + :session + dbus--test-service + dbus--test-path + interface + signal-name))) + (pcase-let ((`(signal ((name . ,name)) . ,rest) signal)) + (should + (string-equal name signal-name)) + (should + (string-equal name (dbus-introspect-get-attribute signal "name"))) + (dbus--test-validate-m-or-s rest expected-annotations expected-args)))) + + +(defsubst dbus--test-examine-method (interface + method-name + expected-annotations + &rest expected-args) + "Validate a method definition for `dbus-test-07-test-introspection'. + +The argument INTERFACE is a string naming the interface owning METHOD-NAME. +The argument METHOD-NAME is a string naming the method to validate. +The arguments EXPECTED-ANNOTATIONS represent the names of the method's properties. +The argument EXPECTED-ARGS is a list of expected arguments for the method." + (let ((method (dbus-introspect-get-method + :session + dbus--test-service + dbus--test-path + interface + method-name))) + (pcase-let ((`(method ((name . ,name)) . ,rest) method)) + (should + (string-equal name method-name)) + (should + (string-equal name (dbus-introspect-get-attribute method "name"))) + (dbus--test-validate-m-or-s rest expected-annotations expected-args)))) + +(ert-deftest dbus-test07-test-introspection () + "Register an Introspection interface then query it." + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + ;; Prepare introspections response + (dbus-register-method :session dbus--test-service + dbus--test-path + dbus-interface-introspectable + "Introspect" + 'dbus--test-introspect) + + (unwind-protect + ;; dbus-introspect-get-node-names + (should + (equal + (dbus-introspect-get-node-names :session dbus--test-service dbus--test-path) + '("node0" "node1"))) + + ;; dbus-introspect-get-all-nodes + + (should + (equal + (dbus-introspect-get-all-nodes :session dbus--test-service dbus--test-path) + (list dbus--test-path (concat dbus--test-path "/node0") (concat dbus--test-path "/node1")))) + + ;; dbus-introspect-get-interface-names + + (let ((interfaces (dbus-introspect-get-interface-names + :session + dbus--test-service + dbus--test-path))) + + (should + (equal + interfaces + `(,dbus-interface-introspectable + ,dbus-interface-properties + ,dbus--test-interface))) + + (dbus--test-examine-interface + dbus-interface-introspectable + nil + '("Introspect") + nil + nil) + + ;; dbus-introspect-get-interface via `dbus--test-examine-interface' + (dbus--test-examine-interface + dbus-interface-properties + nil '("Get" "Set" "GetAll") '("PropertiesChanged") nil) + + (dbus--test-examine-interface + dbus--test-interface + '("Connected" "Player") + '("Connect" "DeprecatedMethod0" "DeprecatedMethod1") + nil + '("org.freedesktop.DBus.Deprecated"))) + + ;; dbus-introspect-get-method-names + + (let ((methods (dbus-introspect-get-method-names + :session + dbus--test-service + dbus--test-path + dbus--test-interface))) + (should + (equal + methods + '("Connect" "DeprecatedMethod0" "DeprecatedMethod1"))) + + ;; dbus-introspect-get-method via 'dbus--test-examine-method + (dbus--test-examine-method + dbus--test-interface + "Connect" + nil + '(arg ((name . "uuid") (type . "s") (direction . "in"))) + '(arg ((name . "mode") (type . "y") (direction . "in"))) + '(arg ((name . "options") (type . "a{sv}") (direction . "in"))) + '(arg ((name . "interface") (type . "s") (direction . "out")))) + + (dbus--test-examine-method + dbus--test-interface + "DeprecatedMethod0" + '("org.freedesktop.DBus.Deprecated")) + + (dbus--test-examine-method + dbus--test-interface + "DeprecatedMethod1" + '("org.freedesktop.DBus.Deprecated"))) + + ;; dbus-introspect-get-signal-names + + (let ((signals (dbus-introspect-get-signal-names + :session + dbus--test-service + dbus--test-path + dbus-interface-properties))) + (should + (equal + signals + '("PropertiesChanged"))) + + ;; dbus-introspect-get-signal via 'dbus--test-examine-signal + (dbus--test-examine-signal + dbus-interface-properties + "PropertiesChanged" + nil + '(arg ((name . "interface") (type . "s"))) + '(arg ((name . "changed_properties") (type . "a{sv}"))) + '(arg ((name . "invalidated_properties") (type . "as"))))) + + ;; dbus-intropct-get-property-names + + (let ((properties (dbus-introspect-get-property-names + :session + dbus--test-service + dbus--test-path + dbus--test-interface))) + (should + (equal + properties + '("Connected" "Player"))) + + ;; dbus-introspect-get-property via 'dbus--test-examine-property + (dbus--test-examine-property + dbus--test-interface + "Connected" + nil + '("Connected" "b" "read") + '("Player" "o" "read")))) + + (dbus-unregister-service :session dbus--test-service)) + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") -- 2.28.0 ^ permalink raw reply related [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-22 3:48 ` Hugh Daschbach @ 2020-09-22 16:09 ` Michael Albinus 2020-09-22 17:36 ` Michael Albinus 1 sibling, 0 replies; 52+ messages in thread From: Michael Albinus @ 2020-09-22 16:09 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, > I have attached two patches for your review. I think the property > tests are complete; I've adjusted the tests to expect errors on > register or set rather than get. Thanks for this. AFAICS, there's nothing left open for bug#43252; I'd like to close it. Is this OK for you? > And, of course, let me know what you think should be reworked. There are only some nits left to comment. > Add DBus tests to validate property handling. Includes cycling We call this beast D-Bus, with a hyphen. Here and everywhere in the docstrings and comments. > register, get, set, get, GetAll, and GetManagedObjects over > several property types. > > Add tests that should fail, like setting a property with a type > different from it's type at registration time. We add also a ChangeLog style entry to the commit message, see the git log of dbus-tests.el. > +The argument SELECTOR indicates whether the test should expand to > +'dbus-register-property' (if SELECTOR is 'register) or `dbus-register' (if SELECTOR is `register') or > +(ert-deftest dbus-test06-test-property-types () The "-test" part of the name seems to be superfluous; I'd call it dbus-test06-property-types. (You see, just nitpicks :-) > + (dbus--test-property > + "Dictionary" > + '((:array > + :dict-entry (:string "four" (:variant :string "value of four")) > + :dict-entry ("five" (:variant :object-path "/nodex")) > + :dict-entry ("six" (:variant (:array :byte 4 :byte 5 :byte 6)))) This is one possibility to declare a :dict-entry. The other possibility, with the same result, is '((:array (:dict-entry :string "four" (:variant :string "value of four")) (:dict-entry "five" (:variant :object-path "/nodex")) (:dict-entry "six" (:variant (:array :byte 4 :byte 5 :byte 6)))) ... Do you mind to test both? > + (should-error ; Cannot set property with :read access > + (equal > + (dbus-set-property > + :session dbus--test-service dbus--test-path > + dbus--test-interface "StringArray" > + '(:array "seven" "eight" :string "nine")) > + nil)) The error happens in dbus-set-property. No need to test further for equal. So you could do (should-error ; Cannot set property with :read access (dbus-set-property :session dbus--test-service dbus--test-path dbus--test-interface "StringArray" '(:array "seven" "eight" :string "nine"))) Furthermore, you could test which error is raised (should-error allows this). Something like (should-error ; Cannot set property with :read access (dbus-set-property :session dbus--test-service dbus--test-path dbus--test-interface "StringArray" '(:array "seven" "eight" :string "nine")) :type 'dbus-error) Similar approach for your other should-error forms. > + ;; Test integer overflow I don't see any integer *overflow* in the following tests. > Thanks, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-22 3:48 ` Hugh Daschbach 2020-09-22 16:09 ` Michael Albinus @ 2020-09-22 17:36 ` Michael Albinus 2020-09-23 3:30 ` Hugh Daschbach 1 sibling, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-22 17:36 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, > I could dig deeper into the dbus-introspect-get-interface, but wanted > to come up for air first. Let me know if you think it's worth the > effort given the individual method, signal, and property tests. Thanks for this! It is already very comprehensive (and takes 2 seconds on my laptop, more than all other tests together). So I guess we could take it as is, until new tests are triggered by errors in the wild. OTOH, I don't mind to give this test the :expensive-test tag. Then it doesn't matter how long it runs. Given the time it consumes, there might be a need to cache introspection data. Either the result of dbus-introspect or dbus--parse-xml-buffer, I guess rather the latter. Do you want to investigate it in dbus.el? > And, of course, let me know what you think should be reworked. Here we are. I don't repeat general comments I have given the other review. > +(defun dbus--test-introspect () > + "Return test introspection string." > + "<?xml version=\"1.0\"?> ... Well, this is one approach. Alternatively, we could regard the introspection file as test data, which is located in a file called .../test/lisp/net/dbus-tests/org.gnu.Emacs.TestDBus.xml. This function (the handler for the Introspect method) would read the file, and return its contents. > +(defsubst dbus--test-examine-interface (iface-name > + expected-properties > + expected-methods > + expected-signals > + expected-annotations) This is rather C-style of argument indentation. In ELisp, we do something like (defsubst dbus--test-examine-interface (iface-name expected-properties expected-methods expected-signals expected-annotations) ...) > + (let ((interface (dbus-introspect-get-interface > + :session > + dbus--test-service > + dbus--test-path > + iface-name))) A similar comment applies. > + (should-not (equal expected nil)) This is (should expected) > + (unwind-protect > + ;; dbus-introspect-get-node-names > + (should > + (equal > + (dbus-introspect-get-node-names :session dbus--test-service dbus--test-path) > + '("node0" "node1"))) A (progn ... is missing after unwind-protect. > + '("org.freedesktop.DBus.Deprecated"))) Hmm. Maybe we shall give "org.freedesktop.DBus.Deprecated" a defconst in dbus.el? > Thanks, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-22 17:36 ` Michael Albinus @ 2020-09-23 3:30 ` Hugh Daschbach 2020-09-23 3:34 ` Hugh Daschbach ` (2 more replies) 0 siblings, 3 replies; 52+ messages in thread From: Hugh Daschbach @ 2020-09-23 3:30 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > > Thanks for this. AFAICS, there's nothing left open for > bug#43252; I'd > like to close it. Is this OK for you? Yes. I was about to suggest this. The issue is resoled. >> And, of course, let me know what you think should be reworked. > > There are only some nits left to comment. Good. Nits promote quality and consistency. >> Add DBus tests to validate property handling. Includes cycling > > We call this beast D-Bus, with a hyphen. Here and everywhere in > the > docstrings and comments. Good. Fixed. > > We add also a ChangeLog style entry to the commit message, see > the git > log of dbus-tests.el. I've taken a shot at this. I'm not sure I got the ChangeLog style correct. Let me know if I'm still off the beaten path. > `dbus-register' (if SELECTOR is `register') or Fixed. >> +(ert-deftest dbus-test06-test-property-types () > > The "-test" part of the name seems to be superfluous; I'd call > it > dbus-test06-property-types. (You see, just nitpicks :-) You say that as if were a bad thing :-). Fixed. >> + (dbus--test-property >> + "Dictionary" >> + '((:array >> + :dict-entry (:string "four" (:variant :string >> "value of four")) >> + :dict-entry ("five" (:variant :object-path >> "/nodex")) >> + :dict-entry ("six" (:variant (:array :byte 4 >> :byte 5 :byte 6)))) > > This is one possibility to declare a :dict-entry. The other > possibility, > with the same result, is > > '((:array > (:dict-entry :string "four" (:variant :string "value of > four")) > (:dict-entry "five" (:variant :object-path "/nodex")) > (:dict-entry "six" (:variant (:array :byte 4 :byte 5 :byte > 6)))) > ... > > Do you mind to test both? I seem to consistently stumble over compound type syntax. Thanks for point this out. Both forms are now tested. >> + (should-error ; Cannot set property >> with :read access >> + (equal ...)) > > The error happens in dbus-set-property. No need to test further > for > equal. So you could do > > (should-error ; Cannot set property with :read > access > (dbus-set-property > :session dbus--test-service dbus--test-path > dbus--test-interface "StringArray" > '(:array "seven" "eight" :string "nine"))) > > Furthermore, you could test which error is raised (should-error > allows > this). Something like > > (should-error ; Cannot set property with :read > access > (dbus-set-property > :session dbus--test-service dbus--test-path > dbus--test-interface "StringArray" > '(:array "seven" "eight" :string "nine")) > :type 'dbus-error) > > Similar approach for your other should-error forms. Got it. I think I've fixed each should-error test. >> + ;; Test integer overflow > > I don't see any integer *overflow* in the following tests. Yes, really botched that. I had a byte truncation test that I only now realize isn't treated as an integer. And that wasn't near the comment. Sigh. I've added conforming and overflow tests. The overflow test, appropriately, error on register. > OTOH, I don't mind to give this test the :expensive-test > tag. Then it > doesn't matter how long it runs. Done. > Given the time it consumes, there might be a need to cache > introspection > data. Either the result of dbus-introspect or > dbus--parse-xml-buffer, I > guess rather the latter. Do you want to investigate it in > dbus.el? Sure. I'll have a look. If I find something useful, I'll open another bug. >> And, of course, let me know what you think should be reworked. > > Here we are. I don't repeat general comments I have given the > other review. > >> +(defun dbus--test-introspect () >> + "Return test introspection string." >> + "<?xml version=\"1.0\"?> > > ... > > Well, this is one approach. Alternatively, we could regard the > introspection file as test data, which is located in a file > called > .../test/lisp/net/dbus-tests/org.gnu.Emacs.TestDBus.xml. This > function > (the handler for the Introspect method) would read the file, and > return > its contents. Makes sense. Done. >> +(defsubst dbus--test-examine-interface (iface-name >> + expected-properties >> + expected-methods >> + expected-signals >> + expected-annotations) > > This is rather C-style of argument indentation. In ELisp, we do > something like Guilty as charged. I'm still working on developing idiomatic elisp. > (defsubst dbus--test-examine-interface > (iface-name expected-properties expected-methods > expected-signals expected-annotations) > ...) > >> + (let ((interface (dbus-introspect-get-interface >> + :session >> + dbus--test-service >> + dbus--test-path >> + iface-name))) > > A similar comment applies. Is: (let* ((property (dbus-introspect-get-property :session dbus--test-service dbus--test-path interface property-name))) ...) preferred over: (let* ((property (dbus-introspect-get-property :session dbus--test-service dbus--test-path interface property-name))) ...) If not, I'll take another bite at the apple. >> + (should-not (equal expected nil)) > > This is (should expected) Yes, I should read what I write. Fixed. Thanks. >> + (unwind-protect >> + ;; dbus-introspect-get-node-names >> + (should >> + (equal >> + (dbus-introspect-get-node-names :session >> dbus--test-service dbus--test-path) >> + '("node0" "node1"))) > A (progn ... is missing after unwind-protect. I really should be more careful when I rip out instrumentation. Thanks for catching this. >> + '("org.freedesktop.DBus.Deprecated"))) > > Hmm. Maybe we shall give "org.freedesktop.DBus.Deprecated" a > defconst in > dbus.el? Done. ’dbus-annotation-deprecated’. Let me know if you think this should be ‘dbus--annotation-deprecated’ instead. >> Thanks, >> Hugh > > Best regards, Michael. In other news, this test: (should-error (dbus-check-arguments :session dbus--test-service :unix-fd 10) :type 'dbus-error) works for me in batch mode, but not interactive mode. On GNU/Linux, (dired (format "/proc/%s/fd" (emacs-pid))) indicates I have 14 open file descriptors on a test instance (emacs -q -Q). On my development instance, I've got 27 open file descriptors. Cheers, Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-23 3:30 ` Hugh Daschbach @ 2020-09-23 3:34 ` Hugh Daschbach 2020-09-23 7:44 ` Michael Albinus 2020-09-23 17:32 ` Michael Albinus 2 siblings, 0 replies; 52+ messages in thread From: Hugh Daschbach @ 2020-09-23 3:34 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 [-- Attachment #1: Type: text/plain, Size: 332 bytes --] Hugh Daschbach writes: > Michael Albinus writes: > >> Hugh Daschbach <hugh@ccss.com> writes: >> >> Hi Hugh, >> >> Thanks for this. AFAICS, there's nothing left open for >> bug#43252; I'd >> like to close it. Is this OK for you? > > Yes. I was about to suggest this. The issue is resoled. Sigh. Forgot to attach new patches. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Property tests. --] [-- Type: text/x-patch, Size: 15528 bytes --] From be45a75b315e56649fa9e39d199fe5e2b50bf69d Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Tue, 22 Sep 2020 19:36:20 -0700 Subject: [PATCH 1/2] Add D-Bus property tests. * test/lisp/net/dbus-tests.el: Add property tests. (dbus--test-run-property-test) (dbus--test-property) (dbus-test06-property-types): Test property registration, set, get. --- test/lisp/net/dbus-tests.el | 431 ++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 62ed3f2bfb4..543b7c8a95b 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -1004,6 +1004,437 @@ dbus-test06-register-property-emits-signal ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(defsubst dbus--test-run-property-test (selector name value expected) + "Generate a property test: register, set, get, getall sequence. +This is a helper function for the macro `dbus--test-property'. +The argument SELECTOR indicates whether the test should expand to +'dbus-register-property' (if SELECTOR is `register') or +`dbus-set-property' (if SELECTOR is `set'). +The argument NAME is the property name. +The argument VALUE is the value to register or set. +The argument EXPECTED is a transformed VALUE representing the +form `dbus-get-property' should return." + (cond + ((eq selector 'register) + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface name :readwrite value) + `((:property :session ,dbus--test-interface ,name) + (,dbus--test-service ,dbus--test-path))))) + + ((eq selector 'set) + (should + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface name value) + expected))) + + (t (signal 'wrong-type-argument "Selector should be 'register or 'set."))) + + (should + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface name) + expected)) + + (let ((result + (dbus-get-all-properties + :session dbus--test-service dbus--test-path + dbus--test-interface))) + (should (equal (cdr (assoc name result)) expected))) + + (let ((result + (dbus-get-all-managed-objects :session dbus--test-service "/")) + result1) + (should (setq result1 (cadr (assoc dbus--test-path result)))) + (should (setq result1 (cadr (assoc dbus--test-interface result1)))) + (should (equal (cdr (assoc name result1)) expected)))) + + +(defsubst dbus--test-property (name &rest value-list) + "Test a D-Bus property named by string argument NAME. + +The argument VALUE-LIST is a sequence of pairs, where each pair +represents a value form and an expected returned value form. The +first pair in VALUES is used for `dbus-register-property'. +Subsequent pairs of the list are tested with +`dbus-set-property'." + (let ((values (car value-list))) + (dbus--test-run-property-test + 'register + name + (car values) + (cdr values))) + (dolist (values (cdr value-list)) + (dbus--test-run-property-test + 'set + name + (car values) + (cdr values)))) + +(ert-deftest dbus-test06-property-types () + "Check property access and mutation for an own service." + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + (unwind-protect + (progn + (dbus--test-property + "ByteArray" + '((:array :byte 1 :byte 2 :byte 3) . (1 2 3)) + '((:array :byte 4 :byte 5 :byte 6) . (4 5 6))) + + (dbus--test-property + "StringArray" + '((:array "one" "two" :string "three") . ("one" "two" "three")) + '((:array :string "four" :string "five" "six") . ("four" "five" "six"))) + + (dbus--test-property + "ObjectArray" + '((:array + :object-path "/node00" + :object-path "/node01" + :object-path "/node0/node02") . + ("/node00" "/node01" "/node0/node02")) + '((:array + :object-path "/node10" + :object-path "/node11" + :object-path "/node0/node12") . + ("/node10" "/node11" "/node0/node12"))) + + (dbus--test-property + "Dictionary" + '((:array + :dict-entry (:string "four" (:variant :string "value of four")) + :dict-entry ("five" (:variant :object-path "/node0")) + :dict-entry ("six" (:variant (:array :byte 4 :byte 5 :byte 6)))) . + (("four" + ("value of four")) + ("five" + ("/node0")) + ("six" + ((4 5 6))))) + '((:array + :dict-entry (:string "key0" (:variant (:array :byte 7 :byte 8 :byte 9))) + :dict-entry ("key1" (:variant :string "value")) + :dict-entry ("key2" (:variant :object-path "/node0/node1"))) . + (("key0" + ((7 8 9))) + ("key1" + ("value")) + ("key2" + ("/node0/node1"))))) + + (dbus--test-property ; Syntax emphasizing :dict compound type + "Dictionary" + '((:array + (:dict-entry :string "seven" (:variant :string "value of seven")) + (:dict-entry "eight" (:variant :object-path "/node8")) + (:dict-entry "nine" (:variant (:array :byte 9 :byte 27 :byte 81)))) . + (("seven" + ("value of seven")) + ("eight" + ("/node8")) + ("nine" + ((9 27 81))))) + '((:array + (:dict-entry :string "key4" (:variant (:array :byte 7 :byte 49 :byte 125))) + (:dict-entry "key5" (:variant :string "obsolete")) + (:dict-entry "key6" (:variant :object-path "/node6/node7"))) . + (("key4" + ((7 49 125))) + ("key5" + ("obsolete")) + ("key6" + ("/node6/node7"))))) + + (dbus--test-property + "ByteDictionary" + '((:array + (:dict-entry :byte 8 (:variant :string "byte-eight")) + (:dict-entry :byte 16 (:variant :object-path "/byte/sixteen")) + (:dict-entry :byte 48 (:variant (:array :byte 8 :byte 9 :byte 10)))) . + ((8 ("byte-eight")) + (16 ("/byte/sixteen")) + (48 ((8 9 10)))))) + + (dbus--test-property + "Variant" + '((:variant "Variant string") . ("Variant string")) + '((:variant :byte 42) . (42)) + '((:variant :uint32 1000000) . (1000000)) + '((:variant :object-path "/variant/path") . ("/variant/path")) + '((:variant :signature "a{sa{sv}}") . ("a{sa{sv}}")) + '((:variant (:struct 42 "string" (:object-path "/structure/path") (:variant "last"))) . + ((42 "string" ("/structure/path") ("last"))))) + + ;; Test that :read prevents writes + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray" :read + '(:array "one" "two" :string "three")) + `((:property :session ,dbus--test-interface "StringArray") + (,dbus--test-service ,dbus--test-path)))) + + (should-error ; Cannot set property with :read access + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray" + '(:array "seven" "eight" :string "nine")) + :type 'dbus-error) + + (should-not + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray") + '("seven" "eight" "nine"))) + + (should ; Verify property has registered value + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "StringArray") + '("one" "two" "three"))) + + ;; Test mismatched types in array + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "MixedArray" :readwrite + '(:array + :object-path "/node00" + :string "/node01" + :object-path "/node0/node02")) + :type 'wrong-type-argument) + + ;; Test in-range integer values + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue" :readwrite + :byte 255) + `((:property :session ,dbus--test-interface "ByteValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + 255)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ShortValue" :readwrite + :int16 32767) + `((:property :session ,dbus--test-interface "ShortValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ShortValue") + 32767)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "UShortValue" :readwrite + :uint16 65535) + `((:property :session ,dbus--test-interface "UShortValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "UShortValue") + 65535)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "IntValue" :readwrite + :int32 2147483647) + `((:property :session ,dbus--test-interface "IntValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "IntValue") + 2147483647)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "UIntValue" :readwrite + :uint32 4294967295) + `((:property :session ,dbus--test-interface "UIntValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "UIntValue") + 4294967295)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "LongValue" :readwrite + :int64 9223372036854775807) + `((:property :session ,dbus--test-interface "LongValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "LongValue") + 9223372036854775807)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ULongValue" :readwrite + :uint64 18446744073709551615) + `((:property :session ,dbus--test-interface "ULongValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ULongValue") + 18446744073709551615)) + + ;; Test integer overflow + + (should + (= + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue" :byte 520) + 8)) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + 8)) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ShortValue" :readwrite + :int16 32800) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "UShortValue" :readwrite + :uint16 65600) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "IntValue" :readwrite + :int32 2147483700) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "UIntValue" :readwrite + :uint32 4294967300) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "LongValue" :readwrite + :int64 9223372036854775900) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ULongValue" :readwrite + :uint64 18446744073709551700) + :type 'args-out-of-range) + + ;; dbus-set-property may change property type + + (should + (= + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue" 1024) + 1024)) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + 1024)) + + + (should ; Another change property type + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue" :boolean t) + t)) + + (should + (eq + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "ByteValue") + t)) + + ;; Test invalid type specification + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface "InvalidType" :readwrite + :keyword 128) + :type 'wrong-type-argument)) + + ;; Cleanup. + + + (message "cleanup") + (dbus-unregister-service :session dbus--test-service))) + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") -- 2.28.0 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #3: Introspection tests. --] [-- Type: text/x-patch, Size: 15848 bytes --] From 3efb1b38d75572b14ac0526dbd79769d6fa89d10 Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Mon, 21 Sep 2020 17:12:49 -0700 Subject: [PATCH 2/2] Add D-Bus Introspection tests. * lisp/net/dbus.el (new defconst): D-Bus deprecation name. * test/lisp/net/dbus-tests.el (dbus--tests-dir) (dbus--test-introspect) (dbus--test-examine-interface) (dbus--test-validate-annotations) (dbus--test-validate-property) (dbus--test-validate-m-or-s) (dbus--test-validate-signal) (dbus--test-validate-method) (dbus-test07-introspection): new tests. * test/lisp/net/dbus-tests/org.gnu.Emacs.TestDBus.xml: new test data. --- lisp/net/dbus.el | 4 + test/lisp/net/dbus-tests.el | 324 ++++++++++++++++++ .../net/dbus-tests/org.gnu.Emacs.TestDBus.xml | 49 +++ 3 files changed, 377 insertions(+) create mode 100644 test/lisp/net/dbus-tests/org.gnu.Emacs.TestDBus.xml diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el index 86db7cbf18a..8da3245800b 100644 --- a/lisp/net/dbus.el +++ b/lisp/net/dbus.el @@ -153,6 +153,10 @@ dbus-interface-local ;; </signal> ;; </interface> +(defconst dbus-annotation-deprecated (concat dbus-interface-dbus ".Deprecated") + "An annotation value indicating a deprecated interface, method, signal, or property.") + + \f ;;; Default D-Bus errors. diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 543b7c8a95b..15d80f79a22 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -44,6 +44,13 @@ dbus--test-path (defconst dbus--test-interface "org.gnu.Emacs.TestDBus.Interface" "Test interface.") +(defvar dbus--tests-dir + (file-truename + (expand-file-name "dbus-tests" + (file-name-directory (or load-file-name + buffer-file-name)))) + "Directory containing test data files.") + (defun dbus--test-availability (bus) "Test availability of D-Bus BUS." (should (dbus-list-names bus)) @@ -1435,6 +1442,323 @@ dbus-test06-property-types (message "cleanup") (dbus-unregister-service :session dbus--test-service))) +(defun dbus--test-introspect () + "Return test introspection string." + (with-temp-buffer + (insert-file (expand-file-name "org.gnu.Emacs.TestDBus.xml" dbus--tests-dir)) + (buffer-string))) + +(defsubst dbus--test-validate-interface + (iface-name expected-properties expected-methods expected-signals + expected-annotations) + "Validate an interface definition for `dbus-test-07-test-introspection'. +The argument IFACE-NAME is a string naming the interface to validate. +The arguments EXPECTED-PROPERTIES, EXPECTED-METHODS, EXPECTED-SIGNALS, and +EXPECTED-ANNOTATIONS represent the names of the interface's properties, +methods, signals, and annotations, respecively." + + (let ((interface + (dbus-introspect-get-interface + :session + dbus--test-service + dbus--test-path + iface-name))) + (pcase-let ((`(interface ((name . ,name)) . ,rest) interface)) + (should + (string-equal name iface-name)) + (should + (string-equal name (dbus-introspect-get-attribute interface "name"))) + + (let (properties methods signals annotations) + (mapc (lambda (x) + (let ((name (dbus-introspect-get-attribute x "name"))) + (cond + ((eq 'property (car x)) (push name properties)) + ((eq 'method (car x)) (push name methods)) + ((eq 'signal (car x)) (push name signals)) + ((eq 'annotation (car x)) (push name annotations))))) + rest) + + (should + (equal + (nreverse properties) + expected-properties)) + (should + (equal + (nreverse methods) + expected-methods)) + (should + (equal + (nreverse signals) + expected-signals)) + (should + (equal + (nreverse annotations) + expected-annotations)))))) + +(defsubst dbus--test-validate-annotations (annotations expected-annotations) + "Validate a list of D-Bus ANNOTATIONS. +Ensure each string in EXPECTED-ANNOTATIONS names an element of ANNOTATIONS. +And ensure each ANNOTATIONS has a value attribute marked \"true\"." + (mapc + (lambda (annotation) + (let ((name (dbus-introspect-get-attribute annotation "name")) + (value (dbus-introspect-get-attribute annotation "value"))) + (should + (member name expected-annotations)) + (should + (equal value "true")))) + annotations)) + +(defsubst dbus--test-validate-property + (interface property-name expected-annotations &rest expected-args) + "Validate a property definition for `dbus-test-07-test-introspection'. + +The argument INTERFACE is a string naming the interface owning PROPERTY-NAME. +The argument PROPERTY-NAME is a string naming the property to validate. +The arguments EXPECTED-ANNOTATIONS represent the names of the property's properties. +The argument EXPECTED-ARGS is a list of expected arguments for the property." + (let* ((property + (dbus-introspect-get-property + :session + dbus--test-service + dbus--test-path interface + property-name)) + (name (dbus-introspect-get-attribute property "name")) + (type (dbus-introspect-get-attribute property "type")) + (access (dbus-introspect-get-attribute property "access")) + (expected (assoc-string name expected-args))) + (should expected) + + (should + (string-equal name property-name)) + + (should + (string-equal + (nth 0 expected) + name)) + + (should + (string-equal + (nth 1 expected) + type)) + + (should + (string-equal + (nth 2 expected) + access)))) + +(defsubst dbus--test-validate-m-or-s (tree expected-annotations expected-args) + "Validate a method or signal definition for `dbus-test-07-test-introspection'. +The argument TREE is an sexp returned from either `dbus-introspect-get-method' +or `dbus-introspect-get-signal' +The arguments EXPECTED-ANNOTATIONS is an sexp matching the annotations defined +for the method or signal. +The argument EXPECTED-ARGS is a list of expected arguments for +the method or signal." + (let (args annotations) + (mapc (lambda (elem) + (let ((name (dbus-introspect-get-attribute elem "name"))) + (cond + ((eq 'arg (car elem)) (push elem args)) + ((eq 'annotation (car elem)) (push elem annotations))))) + tree) + (should + (equal + (nreverse args) + expected-args)) + (dbus--test-validate-annotations annotations expected-annotations))) + +(defsubst dbus--test-validate-signal + (interface signal-name expected-annotations &rest expected-args) + "Validate a signal definition for `dbus-test-07-test-introspection'. + +The argument INTERFACE is a string naming the interface owning SIGNAL-NAME. +The argument SIGNAL-NAME is a string naming the signal to validate. +The arguments EXPECTED-ANNOTATIONS represent the names of the signal's properties. +The argument EXPECTED-ARGS is a list of expected arguments for the signal." + (let ((signal + (dbus-introspect-get-signal + :session + dbus--test-service + dbus--test-path + interface + signal-name))) + (pcase-let ((`(signal ((name . ,name)) . ,rest) signal)) + (should + (string-equal name signal-name)) + (should + (string-equal name (dbus-introspect-get-attribute signal "name"))) + (dbus--test-validate-m-or-s rest expected-annotations expected-args)))) + + +(defsubst dbus--test-validate-method + (interface method-name expected-annotations &rest expected-args) + "Validate a method definition for `dbus-test-07-test-introspection'. + +The argument INTERFACE is a string naming the interface owning METHOD-NAME. +The argument METHOD-NAME is a string naming the method to validate. +The arguments EXPECTED-ANNOTATIONS represent the names of the method's properties. +The argument EXPECTED-ARGS is a list of expected arguments for the method." + (let ((method + (dbus-introspect-get-method + :session + dbus--test-service + dbus--test-path + interface + method-name))) + (pcase-let ((`(method ((name . ,name)) . ,rest) method)) + (should + (string-equal name method-name)) + (should + (string-equal name (dbus-introspect-get-attribute method "name"))) + (dbus--test-validate-m-or-s rest expected-annotations expected-args)))) + +(ert-deftest dbus-test07-introspection () + :tags '(:expensive-test) + "Register an Introspection interface then query it." + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + ;; Prepare introspections response + (dbus-register-method + :session dbus--test-service + dbus--test-path + dbus-interface-introspectable + "Introspect" + 'dbus--test-introspect) + + (unwind-protect + (progn + ;; dbus-introspect-get-node-names + (should + (equal + (dbus-introspect-get-node-names :session dbus--test-service dbus--test-path) + '("node0" "node1"))) + + ;; dbus-introspect-get-all-nodes + + (should + (equal + (dbus-introspect-get-all-nodes :session dbus--test-service dbus--test-path) + (list dbus--test-path + (concat dbus--test-path "/node0") + (concat dbus--test-path "/node1")))) + + ;; dbus-introspect-get-interface-names + + (let ((interfaces + (dbus-introspect-get-interface-names + :session + dbus--test-service + dbus--test-path))) + + (should + (equal + interfaces + `(,dbus-interface-introspectable + ,dbus-interface-properties + ,dbus--test-interface))) + + (dbus--test-validate-interface + dbus-interface-introspectable + nil + '("Introspect") + nil + nil) + + ;; dbus-introspect-get-interface via `dbus--test-validate-interface' + (dbus--test-validate-interface + dbus-interface-properties + nil '("Get" "Set" "GetAll") '("PropertiesChanged") nil) + + (dbus--test-validate-interface + dbus--test-interface + '("Connected" "Player") + '("Connect" "DeprecatedMethod0" "DeprecatedMethod1") + nil + `(,dbus-annotation-deprecated))) + + ;; dbus-introspect-get-method-names + + (let ((methods + (dbus-introspect-get-method-names + :session + dbus--test-service + dbus--test-path + dbus--test-interface))) + (should + (equal + methods + '("Connect" "DeprecatedMethod0" "DeprecatedMethod1"))) + + ;; dbus-introspect-get-method via 'dbus--test-validate-method + + (dbus--test-validate-method + dbus--test-interface + "Connect" + nil + '(arg ((name . "uuid") (type . "s") (direction . "in"))) + '(arg ((name . "mode") (type . "y") (direction . "in"))) + '(arg ((name . "options") (type . "a{sv}") (direction . "in"))) + '(arg ((name . "interface") (type . "s") (direction . "out")))) + + (dbus--test-validate-method + dbus--test-interface + "DeprecatedMethod0" + `(,dbus-annotation-deprecated)) + + (dbus--test-validate-method + dbus--test-interface + "DeprecatedMethod1" + `(,dbus-annotation-deprecated))) + + ;; dbus-introspect-get-signal-names + + (let ((signals + (dbus-introspect-get-signal-names + :session + dbus--test-service + dbus--test-path + dbus-interface-properties))) + (should + (equal + signals + '("PropertiesChanged"))) + + ;; dbus-introspect-get-signal via 'dbus--test-validate-signal + (dbus--test-validate-signal + dbus-interface-properties + "PropertiesChanged" + nil + '(arg ((name . "interface") (type . "s"))) + '(arg ((name . "changed_properties") (type . "a{sv}"))) + '(arg ((name . "invalidated_properties") (type . "as"))))) + + ;; dbus-intropct-get-property-names + + (let ((properties + (dbus-introspect-get-property-names + :session + dbus--test-service + dbus--test-path + dbus--test-interface))) + (should + (equal + properties + '("Connected" "Player"))) + + ;; dbus-introspect-get-property via 'dbus--test-validate-property + (dbus--test-validate-property + dbus--test-interface + "Connected" + nil + '("Connected" "b" "read") + '("Player" "o" "read")))) + + (dbus-unregister-service :session dbus--test-service))) + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") diff --git a/test/lisp/net/dbus-tests/org.gnu.Emacs.TestDBus.xml b/test/lisp/net/dbus-tests/org.gnu.Emacs.TestDBus.xml new file mode 100644 index 00000000000..620f10510f2 --- /dev/null +++ b/test/lisp/net/dbus-tests/org.gnu.Emacs.TestDBus.xml @@ -0,0 +1,49 @@ +<?xml version="1.0"?> +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.freedesktop.DBus.Introspectable"> + <method name="Introspect"> + <arg name="xml" type="s" direction="out"/> + </method> + </interface> + <interface name="org.freedesktop.DBus.Properties"> + <method name="Get"> + <arg name="interface" type="s" direction="in"/> + <arg name="name" type="s" direction="in"/> + <arg name="value" type="v" direction="out"/> + </method> + <method name="Set"> + <arg name="interface" type="s" direction="in"/> + <arg name="name" type="s" direction="in"/> + <arg name="value" type="v" direction="in"/> + </method> + <method name="GetAll"> + <arg name="interface" type="s" direction="in"/> + <arg name="properties" type="a{sv}" direction="out"/> + </method> + <signal name="PropertiesChanged"> + <arg name="interface" type="s"/> + <arg name="changed_properties" type="a{sv}"/> + <arg name="invalidated_properties" type="as"/> + </signal> + </interface> + <interface name="org.gnu.Emacs.TestDBus.Interface"> + <method name="Connect"> + <arg name="uuid" type="s" direction="in"/> + <arg name="mode" type="y" direction="in"/> + <arg name="options" type="a{sv}" direction="in"/> + <arg name="interface" type="s" direction="out"/> + </method> + <method name="DeprecatedMethod0"> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </method> + <method name="DeprecatedMethod1"> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </method> + <property name="Connected" type="b" access="read"/> + <property name="Player" type="o" access="read"/> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </interface> + <node name="node0"/> + <node name="node1"/> +</node> -- 2.28.0 [-- Attachment #4: Type: text/plain, Size: 15 bytes --] Cheers, Hugh ^ permalink raw reply related [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-23 3:30 ` Hugh Daschbach 2020-09-23 3:34 ` Hugh Daschbach @ 2020-09-23 7:44 ` Michael Albinus 2020-09-23 17:32 ` Michael Albinus 2 siblings, 0 replies; 52+ messages in thread From: Michael Albinus @ 2020-09-23 7:44 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252-done Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >> Thanks for this. AFAICS, there's nothing left open for bug#43252; I'd >> like to close it. Is this OK for you? > > Yes. I was about to suggest this. The issue is resoled. Closed. > Cheers, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-23 3:30 ` Hugh Daschbach 2020-09-23 3:34 ` Hugh Daschbach 2020-09-23 7:44 ` Michael Albinus @ 2020-09-23 17:32 ` Michael Albinus 2020-09-24 3:02 ` Hugh Daschbach 2 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-23 17:32 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, > I've taken a shot at this. I'm not sure I got the ChangeLog style > correct. Let me know if I'm still off the beaten path. Almost. See comment below. >> `dbus-register' (if SELECTOR is `register') or > > Fixed. Almost. See comment below. >> Well, this is one approach. Alternatively, we could regard the >> introspection file as test data, which is located in a file called >> .../test/lisp/net/dbus-tests/org.gnu.Emacs.TestDBus.xml. This >> function (the handler for the Introspect method) would read the file, >> and return its contents. Oops, I'm mistaken here. The directory shall be called dbus-resources, see .../test/file-organization.org. Sorry. > Is: > > (let* ((property > (dbus-introspect-get-property > :session > dbus--test-service > dbus--test-path interface > property-name))) ...) > > preferred over: > > (let* ((property > (dbus-introspect-get-property :session > dbus--test-service > dbus--test-path interface property-name))) > ...) > > If not, I'll take another bite at the apple. I'd vote for the latter, with the first argument :session preceding the other arguments in the same line. Like (let* ((property (dbus-introspect-get-property :session dbus--test-service dbus--test-path interface property-name))) ...) If all arguments fit into 80 columns, do it. The "canonical" formatting is offered by the `pp' command (pretty printer). I must confess, that I do not follow all its recommendations. > Done. ’dbus-annotation-deprecated’. Let me know if you think this > should be > ‘dbus--annotation-deprecated’ instead. No, the former is OK. People might want to use it in their packages. > In other news, this test: > > (should-error > (dbus-check-arguments :session dbus--test-service :unix-fd 10) > :type 'dbus-error) > > works for me in batch mode, but not interactive mode. > > On GNU/Linux, (dired (format "/proc/%s/fd" (emacs-pid))) indicates I > have 14 open file descriptors on a test instance (emacs -q -Q). On my > development instance, I've got 27 open file descriptors. I see. Will investigate. And now my review for the latest patch versions. > From be45a75b315e56649fa9e39d199fe5e2b50bf69d Mon Sep 17 00:00:00 2001 > From: Hugh Daschbach <hdasch@fastmail.com> > Date: Tue, 22 Sep 2020 19:36:20 -0700 > Subject: [PATCH 1/2] Add D-Bus property tests. > > * test/lisp/net/dbus-tests.el: Add property tests. > (dbus--test-run-property-test) (dbus--test-property) > (dbus-test06-property-types): Test property registration, set, get. If you have one comment for several functions, use only one parenthesis per line like (dbus--test-run-property-test, dbus--test-property) (dbus-test06-property-types): Test property registration, set, get. > +(defsubst dbus--test-run-property-test (selector name value expected) > + "Generate a property test: register, set, get, getall sequence. > +This is a helper function for the macro `dbus--test-property'. > +The argument SELECTOR indicates whether the test should expand to > +'dbus-register-property' (if SELECTOR is `register') or `dbus-register-property' (if SELECTOR is `register') or > + '((:array > + :object-path "/node00" > + :object-path "/node01" > + :object-path "/node0/node02") . > + ("/node00" "/node01" "/node0/node02")) If a cons cell doesn't fit into one line, you shall move the dot "." to the beginning of the next line, like (dbus--test-property "ObjectArray" '((:array :object-path "/node00" :object-path "/node01" :object-path "/node0/node02") . ("/node00" "/node01" "/node0/node02")) I bet the dot "." has the font-lock-warning-face (red foreground color) in your buffer. Admittedly, it doesn't look prominent :-( Move the cursor over the misplaced dot; there shall be a help message about. > + ;; Cleanup. > + (message "cleanup") > + (dbus-unregister-service :session dbus--test-service))) I don't believe we need this message. We see that we're done :-) > From 3efb1b38d75572b14ac0526dbd79769d6fa89d10 Mon Sep 17 00:00:00 2001 > From: Hugh Daschbach <hdasch@fastmail.com> > Date: Mon, 21 Sep 2020 17:12:49 -0700 > Subject: [PATCH 2/2] Add D-Bus Introspection tests. > > * lisp/net/dbus.el (new defconst): D-Bus deprecation name. > > * test/lisp/net/dbus-tests.el (dbus--tests-dir) > (dbus--test-introspect) (dbus--test-examine-interface) > (dbus--test-validate-annotations) (dbus--test-validate-property) > (dbus--test-validate-m-or-s) (dbus--test-validate-signal) > (dbus--test-validate-method) (dbus-test07-introspection): new tests. That's not true. All but the last functions are new defuns, not new tests. And please start the explanation with a capital letter, like "New test." > +(defconst dbus-annotation-deprecated (concat dbus-interface-dbus ".Deprecated") > + "An annotation value indicating a deprecated interface, method, signal, or property.") The docstring line does not fit 80 chars. What about "An annotation indicating a deprecated interface, method, signal, or property." > +(defvar dbus--tests-dir > + (file-truename > + (expand-file-name "dbus-tests" > + (file-name-directory (or load-file-name > + buffer-file-name)))) > + "Directory containing test data files.") As said, it must be "dbus-resources". > +(ert-deftest dbus-test07-introspection () > + :tags '(:expensive-test) > + "Register an Introspection interface then query it." :tags must be after the docstring. > Cheers, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-23 17:32 ` Michael Albinus @ 2020-09-24 3:02 ` Hugh Daschbach 2020-09-24 8:48 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-24 3:02 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 [-- Attachment #1: Type: text/plain, Size: 2255 bytes --] Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > > Oops, I'm mistaken here. The directory shall be called > dbus-resources, > see .../test/file-organization.org. Sorry. No worries. Done. > I'd vote for the latter, with the first argument :session > preceding > the other arguments in the same line. Like > > (let* ((property > (dbus-introspect-get-property > :session dbus--test-service > dbus--test-path interface property-name))) > ...) I think I've addressed this. I reformatted a few tests that were similarly indented. > If you have one comment for several functions, use only one > parenthesis > per line like > > (dbus--test-run-property-test, dbus--test-property) > (dbus-test06-property-types): Test property registration, set, > get. Done. I think. > `dbus-register-property' (if SELECTOR is `register') or Done. Apologies for not picking up the quoting issue the first time you mentioned it. > I bet the dot "." has the font-lock-warning-face (red foreground > color) > in your buffer. Admittedly, it doesn't look prominent :-( > > Move the cursor over the misplaced dot; there shall be a help > message about. Done. > I don't believe we need this message. We see that we're done :-) Gone. >> * lisp/net/dbus.el (new defconst): D-Bus deprecation name. >> >> * test/lisp/net/dbus-tests.el (dbus--tests-dir) >> (dbus--test-introspect) (dbus--test-examine-interface) >> (dbus--test-validate-annotations) >> (dbus--test-validate-property) >> (dbus--test-validate-m-or-s) (dbus--test-validate-signal) >> (dbus--test-validate-method) (dbus-test07-introspection): new >> tests. I think I understand the ChangeLog format. Additional corrections welcome. > The docstring line does not fit 80 chars. What about > > "An annotation indicating a deprecated interface, method, > signal, or property." Done. >> +(ert-deftest dbus-test07-introspection () >> + :tags '(:expensive-test) >> + "Register an Introspection interface then query it." > > :tags must be after the docstring. Corrected. >> Cheers, >> Hugh > > Best regards, Michael. I think I've addressed all the issues you pointed out. Let me know if there's something that still doesn't look right. Thanks Hugh [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Property tests. --] [-- Type: text/x-patch, Size: 15313 bytes --] From 64dcf1a657a7610709072676905f0157178511eb Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Tue, 22 Sep 2020 19:36:20 -0700 Subject: [PATCH 1/2] Add D-Bus property tests. * test/lisp/net/dbus-tests.el: Add property tests. (dbus--test-run-property-test, dbus--test-property): New defuns. (dbus-test06-property-types): New test for property registration, set, get. --- test/lisp/net/dbus-tests.el | 398 ++++++++++++++++++++++++++++++++++++ 1 file changed, 398 insertions(+) diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 2f20fcc1e67..2e0c061a556 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -1005,6 +1005,404 @@ dbus-test06-register-property-emits-signal ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(defsubst dbus--test-run-property-test (selector name value expected) + "Generate a property test: register, set, get, getall sequence. +This is a helper function for the macro `dbus--test-property'. +The argument SELECTOR indicates whether the test should expand to +`dbus-register-property' (if SELECTOR is `register') or +`dbus-set-property' (if SELECTOR is `set'). +The argument NAME is the property name. +The argument VALUE is the value to register or set. +The argument EXPECTED is a transformed VALUE representing the +form `dbus-get-property' should return." + (cond + ((eq selector 'register) + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface name + :readwrite value) + `((:property :session ,dbus--test-interface ,name) + (,dbus--test-service ,dbus--test-path))))) + + ((eq selector 'set) + (should + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path dbus--test-interface name + value) + expected))) + + (t (signal 'wrong-type-argument "Selector should be 'register or 'set."))) + + (should + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface name) + expected)) + + (let ((result + (dbus-get-all-properties + :session dbus--test-service dbus--test-path dbus--test-interface))) + (should (equal (cdr (assoc name result)) expected))) + + (let ((result + (dbus-get-all-managed-objects :session dbus--test-service "/")) + result1) + (should (setq result1 (cadr (assoc dbus--test-path result)))) + (should (setq result1 (cadr (assoc dbus--test-interface result1)))) + (should (equal (cdr (assoc name result1)) expected)))) + + +(defsubst dbus--test-property (name &rest value-list) + "Test a D-Bus property named by string argument NAME. + +The argument VALUE-LIST is a sequence of pairs, where each pair +represents a value form and an expected returned value form. The +first pair in VALUES is used for `dbus-register-property'. +Subsequent pairs of the list are tested with `dbus-set-property'." + (let ((values (car value-list))) + (dbus--test-run-property-test + 'register name (car values) (cdr values))) + (dolist (values (cdr value-list)) + (dbus--test-run-property-test + 'set name (car values) (cdr values)))) + +(ert-deftest dbus-test06-property-types () + "Check property access and mutation for an own service." + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + (unwind-protect + (progn + (dbus--test-property + "ByteArray" + '((:array :byte 1 :byte 2 :byte 3) . (1 2 3)) + '((:array :byte 4 :byte 5 :byte 6) . (4 5 6))) + + (dbus--test-property + "StringArray" + '((:array "one" "two" :string "three") . ("one" "two" "three")) + '((:array :string "four" :string "five" "six") . ("four" "five" "six"))) + + (dbus--test-property + "ObjectArray" + '((:array + :object-path "/node00" + :object-path "/node01" + :object-path "/node0/node02") + . ("/node00" "/node01" "/node0/node02")) + '((:array + :object-path "/node10" + :object-path "/node11" + :object-path "/node0/node12") + . ("/node10" "/node11" "/node0/node12"))) + + (dbus--test-property + "Dictionary" + '((:array + :dict-entry (:string "four" (:variant :string "value of four")) + :dict-entry ("five" (:variant :object-path "/node0")) + :dict-entry ("six" (:variant (:array :byte 4 :byte 5 :byte 6)))) + . (("four" + ("value of four")) + ("five" + ("/node0")) + ("six" + ((4 5 6))))) + '((:array + :dict-entry (:string "key0" (:variant (:array :byte 7 :byte 8 :byte 9))) + :dict-entry ("key1" (:variant :string "value")) + :dict-entry ("key2" (:variant :object-path "/node0/node1"))) + . (("key0" + ((7 8 9))) + ("key1" + ("value")) + ("key2" + ("/node0/node1"))))) + + (dbus--test-property ; Syntax emphasizing :dict compound type + "Dictionary" + '((:array + (:dict-entry :string "seven" (:variant :string "value of seven")) + (:dict-entry "eight" (:variant :object-path "/node8")) + (:dict-entry "nine" (:variant (:array :byte 9 :byte 27 :byte 81)))) + . (("seven" + ("value of seven")) + ("eight" + ("/node8")) + ("nine" + ((9 27 81))))) + '((:array + (:dict-entry :string "key4" (:variant (:array :byte 7 :byte 49 :byte 125))) + (:dict-entry "key5" (:variant :string "obsolete")) + (:dict-entry "key6" (:variant :object-path "/node6/node7"))) + . (("key4" + ((7 49 125))) + ("key5" + ("obsolete")) + ("key6" + ("/node6/node7"))))) + + (dbus--test-property + "ByteDictionary" + '((:array + (:dict-entry :byte 8 (:variant :string "byte-eight")) + (:dict-entry :byte 16 (:variant :object-path "/byte/sixteen")) + (:dict-entry :byte 48 (:variant (:array :byte 8 :byte 9 :byte 10)))) + . ((8 ("byte-eight")) + (16 ("/byte/sixteen")) + (48 ((8 9 10)))))) + + (dbus--test-property + "Variant" + '((:variant "Variant string") . ("Variant string")) + '((:variant :byte 42) . (42)) + '((:variant :uint32 1000000) . (1000000)) + '((:variant :object-path "/variant/path") . ("/variant/path")) + '((:variant :signature "a{sa{sv}}") . ("a{sa{sv}}")) + '((:variant (:struct 42 "string" (:object-path "/structure/path") (:variant "last"))) + . ((42 "string" ("/structure/path") ("last"))))) + + ;; Test that :read prevents writes + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "StringArray" :read '(:array "one" "two" :string "three")) + `((:property :session ,dbus--test-interface "StringArray") + (,dbus--test-service ,dbus--test-path)))) + + (should-error ; Cannot set property with :read access + (dbus-set-property + :session dbus--test-service dbus--test-path dbus--test-interface + "StringArray" '(:array "seven" "eight" :string "nine")) + :type 'dbus-error) + + (should ; Property value preserved on error + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "StringArray") + '("one" "two" "three"))) + + (should ; Verify property has registered value + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "StringArray") + '("one" "two" "three"))) + + ;; Test mismatched types in array + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "MixedArray" :readwrite + '(:array + :object-path "/node00" + :string "/node01" + :object-path "/node0/node02")) + :type 'wrong-type-argument) + + ;; Test in-range integer values + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue" :readwrite :byte 255) + `((:property :session ,dbus--test-interface "ByteValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue") + 255)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ShortValue" :readwrite :int16 32767) + `((:property :session ,dbus--test-interface "ShortValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ShortValue") + 32767)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UShortValue" :readwrite :uint16 65535) + `((:property :session ,dbus--test-interface "UShortValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UShortValue") + 65535)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "IntValue" :readwrite :int32 2147483647) + `((:property :session ,dbus--test-interface "IntValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "IntValue") + 2147483647)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UIntValue" :readwrite :uint32 4294967295) + `((:property :session ,dbus--test-interface "UIntValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UIntValue") + 4294967295)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "LongValue" :readwrite :int64 9223372036854775807) + `((:property :session ,dbus--test-interface "LongValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "LongValue") + 9223372036854775807)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ULongValue" :readwrite :uint64 18446744073709551615) + `((:property :session ,dbus--test-interface "ULongValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ULongValue") + 18446744073709551615)) + + ;; Test integer overflow + (should + (= + (dbus-set-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue" :byte 520) + 8)) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue") + 8)) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ShortValue" :readwrite :int16 32800) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UShortValue" :readwrite :uint16 65600) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "IntValue" :readwrite :int32 2147483700) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UIntValue" :readwrite :uint32 4294967300) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "LongValue" :readwrite :int64 9223372036854775900) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ULongValue" :readwrite :uint64 18446744073709551700) + :type 'args-out-of-range) + + ;; dbus-set-property may change property type + (should + (= + (dbus-set-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue" 1024) + 1024)) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue") + 1024)) + + + (should ; Another change property type + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue" :boolean t) + t)) + + (should + (eq + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue") + t)) + + ;; Test invalid type specification + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "InvalidType" :readwrite :keyword 128) + :type 'wrong-type-argument)) + + ;; Cleanup. + (dbus-unregister-service :session dbus--test-service))) + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") -- 2.28.0 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #3: Introspection tests. --] [-- Type: text/x-patch, Size: 15886 bytes --] From 86f5834893efb1bc5fe907ce22d4b81260a2c553 Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Mon, 21 Sep 2020 17:12:49 -0700 Subject: [PATCH 2/2] Add D-Bus Introspection tests. * lisp/net/dbus.el (dbus-annotation-deprecated): New defconst. * test/lisp/net/dbus-tests.el (dbus--tests-dir): New defvar. (dbus--test-introspect, dbus--test-validate-interface) (dbus--test-validate-annotations, dbus--test-validate-property) (dbus--test-validate-m-or-s, dbus--test-validate-signal) (dbus--test-validate-method): New defuns. (dbus-test07-introspection): New test. * test/lisp/net/dbus-tests/org.gnu.Emacs.TestDBus.xml: New test data. --- lisp/net/dbus.el | 3 + .../dbus-resources/org.gnu.Emacs.TestDBus.xml | 49 +++ test/lisp/net/dbus-tests.el | 285 +++++++++++++++++- 3 files changed, 336 insertions(+), 1 deletion(-) create mode 100644 test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el index 86db7cbf18a..7d45c859f12 100644 --- a/lisp/net/dbus.el +++ b/lisp/net/dbus.el @@ -153,6 +153,9 @@ dbus-interface-local ;; </signal> ;; </interface> +(defconst dbus-annotation-deprecated (concat dbus-interface-dbus ".Deprecated") + "An annotation indicating a deprecated interface, method, signal, or property.") + \f ;;; Default D-Bus errors. diff --git a/test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml b/test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml new file mode 100644 index 00000000000..620f10510f2 --- /dev/null +++ b/test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml @@ -0,0 +1,49 @@ +<?xml version="1.0"?> +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.freedesktop.DBus.Introspectable"> + <method name="Introspect"> + <arg name="xml" type="s" direction="out"/> + </method> + </interface> + <interface name="org.freedesktop.DBus.Properties"> + <method name="Get"> + <arg name="interface" type="s" direction="in"/> + <arg name="name" type="s" direction="in"/> + <arg name="value" type="v" direction="out"/> + </method> + <method name="Set"> + <arg name="interface" type="s" direction="in"/> + <arg name="name" type="s" direction="in"/> + <arg name="value" type="v" direction="in"/> + </method> + <method name="GetAll"> + <arg name="interface" type="s" direction="in"/> + <arg name="properties" type="a{sv}" direction="out"/> + </method> + <signal name="PropertiesChanged"> + <arg name="interface" type="s"/> + <arg name="changed_properties" type="a{sv}"/> + <arg name="invalidated_properties" type="as"/> + </signal> + </interface> + <interface name="org.gnu.Emacs.TestDBus.Interface"> + <method name="Connect"> + <arg name="uuid" type="s" direction="in"/> + <arg name="mode" type="y" direction="in"/> + <arg name="options" type="a{sv}" direction="in"/> + <arg name="interface" type="s" direction="out"/> + </method> + <method name="DeprecatedMethod0"> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </method> + <method name="DeprecatedMethod1"> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </method> + <property name="Connected" type="b" access="read"/> + <property name="Player" type="o" access="read"/> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </interface> + <node name="node0"/> + <node name="node1"/> +</node> diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 2e0c061a556..b764e8dc8db 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -44,6 +44,13 @@ dbus--test-path (defconst dbus--test-interface "org.gnu.Emacs.TestDBus.Interface" "Test interface.") +(defvar dbus--tests-dir + (file-truename + (expand-file-name "dbus-resources" + (file-name-directory (or load-file-name + buffer-file-name)))) + "Directory containing introspection test data file.") + (defun dbus--test-availability (bus) "Test availability of D-Bus BUS." (should (dbus-list-names bus)) @@ -1056,7 +1063,6 @@ dbus--test-run-property-test (defsubst dbus--test-property (name &rest value-list) "Test a D-Bus property named by string argument NAME. - The argument VALUE-LIST is a sequence of pairs, where each pair represents a value form and an expected returned value form. The first pair in VALUES is used for `dbus-register-property'. @@ -1403,6 +1409,283 @@ dbus-test06-property-types ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(defun dbus--test-introspect () + "Return test introspection string." + (with-temp-buffer + (insert-file (expand-file-name "org.gnu.Emacs.TestDBus.xml" dbus--tests-dir)) + (buffer-string))) + +(defsubst dbus--test-validate-interface + (iface-name expected-properties expected-methods expected-signals + expected-annotations) + "Validate an interface definition for `dbus-test07-introspection'. +The argument IFACE-NAME is a string naming the interface to validate. +The arguments EXPECTED-PROPERTIES, EXPECTED-METHODS, EXPECTED-SIGNALS, and +EXPECTED-ANNOTATIONS represent the names of the interface's properties, +methods, signals, and annotations, respectively." + + (let ((interface + (dbus-introspect-get-interface + :session dbus--test-service dbus--test-path iface-name))) + (pcase-let ((`(interface ((name . ,name)) . ,rest) interface)) + (should + (string-equal name iface-name)) + (should + (string-equal name (dbus-introspect-get-attribute interface "name"))) + + (let (properties methods signals annotations) + (mapc (lambda (x) + (let ((name (dbus-introspect-get-attribute x "name"))) + (cond + ((eq 'property (car x)) (push name properties)) + ((eq 'method (car x)) (push name methods)) + ((eq 'signal (car x)) (push name signals)) + ((eq 'annotation (car x)) (push name annotations))))) + rest) + + (should + (equal + (nreverse properties) + expected-properties)) + (should + (equal + (nreverse methods) + expected-methods)) + (should + (equal + (nreverse signals) + expected-signals)) + (should + (equal + (nreverse annotations) + expected-annotations)))))) + +(defsubst dbus--test-validate-annotations (annotations expected-annotations) + "Validate a list of D-Bus ANNOTATIONS. +Ensure each string in EXPECTED-ANNOTATIONS names an element of ANNOTATIONS. +And ensure each ANNOTATIONS has a value attribute marked \"true\"." + (mapc + (lambda (annotation) + (let ((name (dbus-introspect-get-attribute annotation "name")) + (value (dbus-introspect-get-attribute annotation "value"))) + (should + (member name expected-annotations)) + (should + (equal value "true")))) + annotations)) + +(defsubst dbus--test-validate-property + (interface property-name expected-annotations &rest expected-args) + "Validate a property definition for `dbus-test07-introspection'. + +The argument INTERFACE is a string naming the interface owning PROPERTY-NAME. +The argument PROPERTY-NAME is a string naming the property to validate. +The arguments EXPECTED-ANNOTATIONS is a list of strings matching +the annotation names defined for the method or signal. +The argument EXPECTED-ARGS is a list of expected arguments for the property." + (let* ((property + (dbus-introspect-get-property + :session dbus--test-service dbus--test-path interface property-name)) + (name (dbus-introspect-get-attribute property "name")) + (type (dbus-introspect-get-attribute property "type")) + (access (dbus-introspect-get-attribute property "access")) + (expected (assoc-string name expected-args))) + (should expected) + + (should + (string-equal name property-name)) + + (should + (string-equal + (nth 0 expected) + name)) + + (should + (string-equal + (nth 1 expected) + type)) + + (should + (string-equal + (nth 2 expected) + access)))) + +(defsubst dbus--test-validate-m-or-s (tree expected-annotations expected-args) + "Validate a method or signal definition for `dbus-test07-introspection'. +The argument TREE is an sexp returned from either `dbus-introspect-get-method' +or `dbus-introspect-get-signal' +The arguments EXPECTED-ANNOTATIONS is a list of strings matching +the annotation names defined for the method or signal. +The argument EXPECTED-ARGS is a list of expected arguments for +the method or signal." + (let (args annotations) + (mapc (lambda (elem) + (let ((name (dbus-introspect-get-attribute elem "name"))) + (cond + ((eq 'arg (car elem)) (push elem args)) + ((eq 'annotation (car elem)) (push elem annotations))))) + tree) + (should + (equal + (nreverse args) + expected-args)) + (dbus--test-validate-annotations annotations expected-annotations))) + +(defsubst dbus--test-validate-signal + (interface signal-name expected-annotations &rest expected-args) + "Validate a signal definition for `dbus-test07-introspection'. + +The argument INTERFACE is a string naming the interface owning SIGNAL-NAME. +The argument SIGNAL-NAME is a string naming the signal to validate. +The arguments EXPECTED-ANNOTATIONS is a list of strings matching +the annotation names defined for the signal. +The argument EXPECTED-ARGS is a list of expected arguments for the signal." + (let ((signal + (dbus-introspect-get-signal + :session dbus--test-service dbus--test-path interface signal-name))) + (pcase-let ((`(signal ((name . ,name)) . ,rest) signal)) + (should + (string-equal name signal-name)) + (should + (string-equal name (dbus-introspect-get-attribute signal "name"))) + (dbus--test-validate-m-or-s rest expected-annotations expected-args)))) + + +(defsubst dbus--test-validate-method + (interface method-name expected-annotations &rest expected-args) + "Validate a method definition for `dbus-test07-introspection'. + +The argument INTERFACE is a string naming the interface owning METHOD-NAME. +The argument METHOD-NAME is a string naming the method to validate. +The arguments EXPECTED-ANNOTATIONS is a list of strings matching +the annotation names defined for the method. +The argument EXPECTED-ARGS is a list of expected arguments for the method." + (let ((method + (dbus-introspect-get-method + :session dbus--test-service dbus--test-path interface method-name))) + (pcase-let ((`(method ((name . ,name)) . ,rest) method)) + (should + (string-equal name method-name)) + (should + (string-equal name (dbus-introspect-get-attribute method "name"))) + (dbus--test-validate-m-or-s rest expected-annotations expected-args)))) + +(ert-deftest dbus-test07-introspection () + "Register an Introspection interface then query it." + :tags '(:expensive-test) + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + ;; Prepare introspection response + (dbus-register-method + :session dbus--test-service dbus--test-path dbus-interface-introspectable + "Introspect" 'dbus--test-introspect) + + (unwind-protect + (progn + ;; dbus-introspect-get-node-names + (should + (equal + (dbus-introspect-get-node-names + :session dbus--test-service dbus--test-path) + '("node0" "node1"))) + + ;; dbus-introspect-get-all-nodes + (should + (equal + (dbus-introspect-get-all-nodes + :session dbus--test-service dbus--test-path) + (list dbus--test-path + (concat dbus--test-path "/node0") + (concat dbus--test-path "/node1")))) + + ;; dbus-introspect-get-interface-names + (let ((interfaces + (dbus-introspect-get-interface-names + :session dbus--test-service dbus--test-path))) + + (should + (equal + interfaces + `(,dbus-interface-introspectable + ,dbus-interface-properties + ,dbus--test-interface))) + + (dbus--test-validate-interface + dbus-interface-introspectable nil '("Introspect") nil nil) + + ;; dbus-introspect-get-interface via `dbus--test-validate-interface' + (dbus--test-validate-interface + dbus-interface-properties nil + '("Get" "Set" "GetAll") '("PropertiesChanged") nil) + + (dbus--test-validate-interface + dbus--test-interface '("Connected" "Player") + '("Connect" "DeprecatedMethod0" "DeprecatedMethod1") nil + `(,dbus-annotation-deprecated))) + + ;; dbus-introspect-get-method-names + (let ((methods + (dbus-introspect-get-method-names + :session dbus--test-service dbus--test-path + dbus--test-interface))) + (should + (equal + methods + '("Connect" "DeprecatedMethod0" "DeprecatedMethod1"))) + + ;; dbus-introspect-get-method via 'dbus--test-validate-method + (dbus--test-validate-method + dbus--test-interface "Connect" nil + '(arg ((name . "uuid") (type . "s") (direction . "in"))) + '(arg ((name . "mode") (type . "y") (direction . "in"))) + '(arg ((name . "options") (type . "a{sv}") (direction . "in"))) + '(arg ((name . "interface") (type . "s") (direction . "out")))) + + (dbus--test-validate-method + dbus--test-interface "DeprecatedMethod0" + `(,dbus-annotation-deprecated)) + + (dbus--test-validate-method + dbus--test-interface "DeprecatedMethod1" + `(,dbus-annotation-deprecated))) + + ;; dbus-introspect-get-signal-names + (let ((signals + (dbus-introspect-get-signal-names + :session dbus--test-service dbus--test-path + dbus-interface-properties))) + (should + (equal + signals + '("PropertiesChanged"))) + + ;; dbus-introspect-get-signal via 'dbus--test-validate-signal + (dbus--test-validate-signal + dbus-interface-properties "PropertiesChanged" nil + '(arg ((name . "interface") (type . "s"))) + '(arg ((name . "changed_properties") (type . "a{sv}"))) + '(arg ((name . "invalidated_properties") (type . "as"))))) + + ;; dbus-intropct-get-property-names + (let ((properties + (dbus-introspect-get-property-names + :session dbus--test-service dbus--test-path + dbus--test-interface))) + (should + (equal + properties + '("Connected" "Player"))) + + ;; dbus-introspect-get-property via 'dbus--test-validate-property + (dbus--test-validate-property + dbus--test-interface "Connected" nil + '("Connected" "b" "read") + '("Player" "o" "read")))) + + (dbus-unregister-service :session dbus--test-service))) + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") -- 2.28.0 ^ permalink raw reply related [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-24 3:02 ` Hugh Daschbach @ 2020-09-24 8:48 ` Michael Albinus 2020-09-25 4:16 ` Hugh Daschbach 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-24 8:48 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, > I think I've addressed all the issues you pointed out. Let me know if > there's something that still doesn't look right. I've roughly scanned the patches, they look almost OK. Let's wait now for appearing your name on the copyright file. Anyway, here's my nit of the day: > * test/lisp/net/dbus-tests/org.gnu.Emacs.TestDBus.xml: New test data. This shall be dbus-resources. > Thanks > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-24 8:48 ` Michael Albinus @ 2020-09-25 4:16 ` Hugh Daschbach 2020-09-26 1:27 ` Hugh Daschbach 0 siblings, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-25 4:16 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > >> I think I've addressed all the issues you pointed out. Let me know if >> there's something that still doesn't look right. > > I've roughly scanned the patches, they look almost OK. Let's wait now > for appearing your name on the copyright file. > > Anyway, here's my nit of the day: > >> * test/lisp/net/dbus-tests/org.gnu.Emacs.TestDBus.xml: New test data. > > This shall be dbus-resources. Thanks. Fixed. Will wait for the paperwork to clear. Then will rebase and send you a final copy of the patches. >> Thanks >> Hugh > > Best regards, Michael. I've taken a brief look at performance of the introspection tests. The long pole seems to be ERT, rather than the tests themselves. Running the profiler while running ert showed The cpu profiler report for running dbus-test07-introspection breaks down something like: - GC - 30% - dbus-* - 30% - ert-* - 40% So I pulled introspection tests out into a separate file, redefined `should', and reran dbus-test07-introspection. It completed almost instantly. I wrapped the body of dbus-test07-introspection in a dotimes form with 50 iterations. That completes in roughly 1.1 seconds. Comparing runtime and GC cycles for a single run, running with ERT: 2 gcs in 2.228295 sec running w/o ERT: 1 gcs in 0.036733 sec Those numbers come from: (let ((start (current-time)) (gcs gcs-done)) ;; test program call (message "%d gcs in %02f sec" (- gcs-done gcs) (float-time (time-since start)))) I'm not well versed in chasing Emacs performance issues, bit this looks to me more like testing than introspection overhead. Any suggestions? Cheers, Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-25 4:16 ` Hugh Daschbach @ 2020-09-26 1:27 ` Hugh Daschbach 2020-09-26 9:51 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-26 1:27 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Hugh Daschbach writes: > I've taken a brief look at performance of the introspection tests. The > long pole seems to be ERT, rather than the tests themselves. > ... > I'm not well versed in chasing Emacs performance issues, bit this looks > to me more like testing than introspection overhead. Any > suggestions? Wrong again. Digging further, I find that my performance tests were in error. Fixing that, elp helped me find that the performance hit came from mishandling incoming introspection requests in ‘dbus--test-introspect’. I hadn’t registered ‘dbus--test-introspect’ for the two subnodes exposed in the xml file. So introspecting those nodes timed out. Each timeout cost a second. I’ve fixed this for the next patch set. The change was simple enough. I think that can wait until the paperwork clears, unless you want an earlier look. Cheers, Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-26 1:27 ` Hugh Daschbach @ 2020-09-26 9:51 ` Michael Albinus 2020-09-28 3:00 ` Hugh Daschbach 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-26 9:51 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, > Fixing that, elp helped me find that the performance hit came from > mishandling incoming introspection requests in ‘dbus--test-introspect’. Good to know. Introspection isn't to punish :-) > I hadn’t registered ‘dbus--test-introspect’ for the two subnodes exposed > in the xml file. So introspecting those nodes timed out. Each timeout > cost a second. OK. But maybe you add also one or two tests to check this error functionality. > I’ve fixed this for the next patch set. The change was simple enough. > I think that can wait until the paperwork clears, unless you want an > earlier look. Sure, this can wait. Btw, I have just pushed a larger patch to master. It implements a first shot on the org.freedesktop.DBus.Monitoring.BecomeMonitor functionality. If you want to see how it works, just call (dbus-register-monitor :session) . There will be a new buffer *D-Bus Monitor*, which shows you D-Bus messages similar to what the UNIX command "dbus-monitor --session" does. The point is that you can register your own handler to the monitor; if you don't declare an own handler, the default handler `dbus-monitor-handler' is taken. As said, it is just a first shot. Proper documentation is missing, and not all arguments of `dbus-register-monitor' seem to work as expected. But you might see which direction it will go; any feedback is appreciated. > Cheers, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-26 9:51 ` Michael Albinus @ 2020-09-28 3:00 ` Hugh Daschbach 2020-09-28 12:55 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-28 3:00 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > >> in the xml file. So introspecting those nodes timed out. Each timeout >> cost a second. > > OK. But maybe you add also one or two tests to check this error functionality. Done. dbus-test07-introspection now has a test that no timeout occurred. It is no longer tagged :expensive-test. A new dbus-test07-timeout tests both implicit (dbus-introspect-*) and explicit (dbus-call-method) timeouts. It is tagged :expensive-test. >> I’ve fixed this for the next patch set. The change was simple enough. > Btw, I have just pushed a larger patch to master. It implements a first > shot on the org.freedesktop.DBus.Monitoring.BecomeMonitor > functionality. If you want to see how it works, just call > (dbus-register-monitor :session) . There will be a new buffer *D-Bus > Monitor*, which shows you D-Bus messages similar to what the UNIX > command "dbus-monitor --session" does. The point is that you can > register your own handler to the monitor; if you don't declare an own > handler, the default handler `dbus-monitor-handler' is taken. > > As said, it is just a first shot. Proper documentation is missing, and > not all arguments of `dbus-register-monitor' seem to work as > expected. But you might see which direction it will go; any feedback is > appreciated. Impressive. This is a great source of proper signature syntax. Not to mention a most useful debugging tool. Nice. Timestamps (perhaps optional) would be useful, I think. Cheers, Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-28 3:00 ` Hugh Daschbach @ 2020-09-28 12:55 ` Michael Albinus 2020-09-28 23:17 ` Hugh Daschbach 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-28 12:55 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, > A new dbus-test07-timeout tests both implicit (dbus-introspect-*) and > explicit (dbus-call-method) timeouts. It is tagged :expensive-test. I like the idea of having test groups (identified by test<NN>). This makes it more easy to select only tests I'm interested in. Could you, pls, move the dbus-call-method timeout test into a test of its own, dbus-test04-call-method-timeout? And the other test might be called dbus-test07-introspect-timeout. > Timestamps (perhaps optional) would be useful, I think. Added. In case of method-return and error messages, I've added also the time difference to the corresponding method-call. And while I'm there, I've added also links between serial numbers. That is, if you click on the serial number of a message-return or error message, you jump to the corresponding methoid-call. And vice-versa. > Cheers, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-28 12:55 ` Michael Albinus @ 2020-09-28 23:17 ` Hugh Daschbach 2020-09-29 12:22 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-28 23:17 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 [-- Attachment #1: Type: text/plain, Size: 772 bytes --] Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > > Could you, pls, move the dbus-call-method timeout test into a test of > its own, dbus-test04-call-method-timeout? And the other test might be > called dbus-test07-introspect-timeout. Sure. I've attached a draft for your review. >> Timestamps (perhaps optional) would be useful, I think. > > Added. In case of method-return and error messages, I've added also the > time difference to the corresponding method-call. Nice. > And while I'm there, I've added also links between serial numbers. That > is, if you click on the serial number of a message-return or error > message, you jump to the corresponding methoid-call. And vice-versa. That's awesome. Great feature. Cheers, Hugh [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Timeout tests. --] [-- Type: text/x-patch, Size: 2473 bytes --] From 454a9f4505bde8068675dfdf58658f752f561729 Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Mon, 28 Sep 2020 12:44:34 -0700 Subject: [PATCH 3/4] Add D-Bus timeout tests. * test/lisp/net/dbus-tests.el: Add timeout tests. (dbus-test04-call-method-timeout, dbus-test07-introspection-timeout): New tests. --- test/lisp/net/dbus-tests.el | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 28dcdd95c00..308f22eb6cc 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -581,6 +581,28 @@ dbus-test04-register-method ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(ert-deftest dbus-test04-call-method-timeout () + "Verify `dbus-call-method' request timeout." + :tags '(:expensive-test) + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + (unwind-protect + (let ((start (current-time))) + ;; Test timeout override for method call. + (should-error + (dbus-call-method + :session dbus--test-service dbus--test-path + dbus-interface-introspectable "Introspect" :timeout 2500) + :type 'dbus-error) + + (should + (< 2.4 (float-time (time-since start)) 2.7))) + + (dbus-unregister-service :session dbus--test-service))) + + (defvar dbus--test-signal-received nil "Received signal value in `dbus--test-signal-handler'.") @@ -1709,6 +1731,22 @@ dbus-test07-introspection (dbus-unregister-service :session dbus--test-service))) +(ert-deftest dbus-test07-introspection-timeout () + "Verify introspection request timeouts." + :tags '(:expensive-test) + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + (unwind-protect + (let ((start (current-time))) + (dbus-introspect-xml :session dbus--test-service dbus--test-path) + ;; Introspection internal timeout is one second. + (should + (< 1.0 (float-time (time-since start))))) + + (dbus-unregister-service :session dbus--test-service))) + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") -- 2.28.0 ^ permalink raw reply related [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-28 23:17 ` Hugh Daschbach @ 2020-09-29 12:22 ` Michael Albinus 2020-09-29 21:51 ` Hugh Daschbach 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-29 12:22 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, >> Could you, pls, move the dbus-call-method timeout test into a test of >> its own, dbus-test04-call-method-timeout? And the other test might be >> called dbus-test07-introspect-timeout. > > Sure. I've attached a draft for your review. Thanks. LGTM. > Cheers, > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-29 12:22 ` Michael Albinus @ 2020-09-29 21:51 ` Hugh Daschbach 2020-09-30 9:34 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Hugh Daschbach @ 2020-09-29 21:51 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 [-- Attachment #1: Type: text/plain, Size: 342 bytes --] Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > > Thanks. LGTM. Thanks. I received the FSF signed copyright document. So we should be clear for submission. I've attached the four patches that we've been discussing: three for bug#43252 and on for bug#43251. Thanks for your patience and guidance. Hugh [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Property tests. --] [-- Type: text/x-patch, Size: 15325 bytes --] From dab1113aa7ae964d888d0e3b00466d55292f035d Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Tue, 22 Sep 2020 19:36:20 -0700 Subject: [PATCH 1/4] Add D-Bus property tests. * test/lisp/net/dbus-tests.el: Add property tests. (dbus--test-run-property-test, dbus--test-property): New defuns. (dbus-test06-property-types): New test for property registration, set, get. --- test/lisp/net/dbus-tests.el | 396 ++++++++++++++++++++++++++++++++++++ 1 file changed, 396 insertions(+) diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index b853542a1f0..fcbb378b44f 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -1018,6 +1018,402 @@ dbus-test06-register-property-emits-signal ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(defsubst dbus--test-run-property-test (selector name value expected) + "Generate a property test: register, set, get, getall sequence. +This is a helper function for the macro `dbus--test-property'. +The argument SELECTOR indicates whether the test should expand to +`dbus-register-property' (if SELECTOR is `register') or +`dbus-set-property' (if SELECTOR is `set'). +The argument NAME is the property name. +The argument VALUE is the value to register or set. +The argument EXPECTED is a transformed VALUE representing the +form `dbus-get-property' should return." + (cond + ((eq selector 'register) + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface name + :readwrite value) + `((:property :session ,dbus--test-interface ,name) + (,dbus--test-service ,dbus--test-path))))) + + ((eq selector 'set) + (should + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path dbus--test-interface name + value) + expected))) + + (t (signal 'wrong-type-argument "Selector should be 'register or 'set."))) + + (should + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface name) + expected)) + + (let ((result + (dbus-get-all-properties + :session dbus--test-service dbus--test-path dbus--test-interface))) + (should (equal (cdr (assoc name result)) expected))) + + (let ((result + (dbus-get-all-managed-objects :session dbus--test-service "/")) + result1) + (should (setq result1 (cadr (assoc dbus--test-path result)))) + (should (setq result1 (cadr (assoc dbus--test-interface result1)))) + (should (equal (cdr (assoc name result1)) expected)))) + + +(defsubst dbus--test-property (name &rest value-list) + "Test a D-Bus property named by string argument NAME. +The argument VALUE-LIST is a sequence of pairs, where each pair +represents a value form and an expected returned value form. The +first pair in VALUES is used for `dbus-register-property'. +Subsequent pairs of the list are tested with `dbus-set-property'." + (let ((values (car value-list))) + (dbus--test-run-property-test + 'register name (car values) (cdr values))) + (dolist (values (cdr value-list)) + (dbus--test-run-property-test + 'set name (car values) (cdr values)))) + +(ert-deftest dbus-test06-property-types () + "Check property access and mutation for an own service." + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + (unwind-protect + (progn + (dbus--test-property + "ByteArray" + '((:array :byte 1 :byte 2 :byte 3) . (1 2 3)) + '((:array :byte 4 :byte 5 :byte 6) . (4 5 6))) + + (dbus--test-property + "StringArray" + '((:array "one" "two" :string "three") . ("one" "two" "three")) + '((:array :string "four" :string "five" "six") . ("four" "five" "six"))) + + (dbus--test-property + "ObjectArray" + '((:array + :object-path "/node00" + :object-path "/node01" + :object-path "/node0/node02") + . ("/node00" "/node01" "/node0/node02")) + '((:array + :object-path "/node10" + :object-path "/node11" + :object-path "/node0/node12") + . ("/node10" "/node11" "/node0/node12"))) + + (dbus--test-property + "Dictionary" + '((:array + :dict-entry (:string "four" (:variant :string "value of four")) + :dict-entry ("five" (:variant :object-path "/node0")) + :dict-entry ("six" (:variant (:array :byte 4 :byte 5 :byte 6)))) + . (("four" + ("value of four")) + ("five" + ("/node0")) + ("six" + ((4 5 6))))) + '((:array + :dict-entry (:string "key0" (:variant (:array :byte 7 :byte 8 :byte 9))) + :dict-entry ("key1" (:variant :string "value")) + :dict-entry ("key2" (:variant :object-path "/node0/node1"))) + . (("key0" + ((7 8 9))) + ("key1" + ("value")) + ("key2" + ("/node0/node1"))))) + + (dbus--test-property ; Syntax emphasizing :dict compound type. + "Dictionary" + '((:array + (:dict-entry :string "seven" (:variant :string "value of seven")) + (:dict-entry "eight" (:variant :object-path "/node8")) + (:dict-entry "nine" (:variant (:array :byte 9 :byte 27 :byte 81)))) + . (("seven" + ("value of seven")) + ("eight" + ("/node8")) + ("nine" + ((9 27 81))))) + '((:array + (:dict-entry :string "key4" (:variant (:array :byte 7 :byte 49 :byte 125))) + (:dict-entry "key5" (:variant :string "obsolete")) + (:dict-entry "key6" (:variant :object-path "/node6/node7"))) + . (("key4" + ((7 49 125))) + ("key5" + ("obsolete")) + ("key6" + ("/node6/node7"))))) + + (dbus--test-property + "ByteDictionary" + '((:array + (:dict-entry :byte 8 (:variant :string "byte-eight")) + (:dict-entry :byte 16 (:variant :object-path "/byte/sixteen")) + (:dict-entry :byte 48 (:variant (:array :byte 8 :byte 9 :byte 10)))) + . ((8 ("byte-eight")) + (16 ("/byte/sixteen")) + (48 ((8 9 10)))))) + + (dbus--test-property + "Variant" + '((:variant "Variant string") . ("Variant string")) + '((:variant :byte 42) . (42)) + '((:variant :uint32 1000000) . (1000000)) + '((:variant :object-path "/variant/path") . ("/variant/path")) + '((:variant :signature "a{sa{sv}}") . ("a{sa{sv}}")) + '((:variant (:struct 42 "string" (:object-path "/structure/path") (:variant "last"))) + . ((42 "string" ("/structure/path") ("last"))))) + + ;; Test that :read prevents writes. + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "StringArray" :read '(:array "one" "two" :string "three")) + `((:property :session ,dbus--test-interface "StringArray") + (,dbus--test-service ,dbus--test-path)))) + + (should-error ; Cannot set property with :read access. + (dbus-set-property + :session dbus--test-service dbus--test-path dbus--test-interface + "StringArray" '(:array "seven" "eight" :string "nine")) + :type 'dbus-error) + + (should ; Property value preserved on error. + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "StringArray") + '("one" "two" "three"))) + + (should ; Verify property has registered value. + (equal + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "StringArray") + '("one" "two" "three"))) + + ;; Test mismatched types in array. + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "MixedArray" :readwrite + '(:array + :object-path "/node00" + :string "/node01" + :object-path "/node0/node02")) + :type 'wrong-type-argument) + + ;; Test in-range integer values. + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue" :readwrite :byte 255) + `((:property :session ,dbus--test-interface "ByteValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue") + 255)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ShortValue" :readwrite :int16 32767) + `((:property :session ,dbus--test-interface "ShortValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ShortValue") + 32767)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UShortValue" :readwrite :uint16 65535) + `((:property :session ,dbus--test-interface "UShortValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UShortValue") + 65535)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "IntValue" :readwrite :int32 2147483647) + `((:property :session ,dbus--test-interface "IntValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface "IntValue") + 2147483647)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UIntValue" :readwrite :uint32 4294967295) + `((:property :session ,dbus--test-interface "UIntValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UIntValue") + 4294967295)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "LongValue" :readwrite :int64 9223372036854775807) + `((:property :session ,dbus--test-interface "LongValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "LongValue") + 9223372036854775807)) + + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ULongValue" :readwrite :uint64 18446744073709551615) + `((:property :session ,dbus--test-interface "ULongValue") + (,dbus--test-service ,dbus--test-path)))) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ULongValue") + 18446744073709551615)) + + ;; Test integer overflow. + (should + (= + (dbus-set-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue" :byte 520) + 8)) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue") + 8)) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ShortValue" :readwrite :int16 32800) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UShortValue" :readwrite :uint16 65600) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "IntValue" :readwrite :int32 2147483700) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "UIntValue" :readwrite :uint32 4294967300) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "LongValue" :readwrite :int64 9223372036854775900) + :type 'args-out-of-range) + + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ULongValue" :readwrite :uint64 18446744073709551700) + :type 'args-out-of-range) + + ;; dbus-set-property may change property type. + (should + (= + (dbus-set-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue" 1024) + 1024)) + + (should + (= + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue") + 1024)) + + + (should ; Another change property type test. + (equal + (dbus-set-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue" :boolean t) + t)) + + (should + (eq + (dbus-get-property + :session dbus--test-service dbus--test-path dbus--test-interface + "ByteValue") + t)) + + ;; Test invalid type specification. + (should-error + (dbus-register-property + :session dbus--test-service dbus--test-path dbus--test-interface + "InvalidType" :readwrite :keyword 128) + :type 'wrong-type-argument)) + + ;; Cleanup. + (dbus-unregister-service :session dbus--test-service))) + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") -- 2.28.0 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #3: Introspection tests. --] [-- Type: text/x-patch, Size: 16061 bytes --] From 1c250268d4e72ec5ff26f29e99ce138e9d22aaf3 Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Tue, 22 Sep 2020 19:36:20 -0700 Subject: [PATCH 2/4] Add D-Bus Introspection tests. * lisp/net/dbus.el (dbus-annotation-deprecated): New defconst. * test/lisp/net/dbus-tests.el (dbus--tests-dir): New defvar. (dbus--test-introspect, dbus--test-validate-interface) (dbus--test-validate-annotations, dbus--test-validate-property) (dbus--test-validate-m-or-s, dbus--test-validate-signal) (dbus--test-validate-method): New defuns. (dbus-test07-introspection): New test. * test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml: New test data. --- lisp/net/dbus.el | 3 + .../dbus-resources/org.gnu.Emacs.TestDBus.xml | 49 +++ test/lisp/net/dbus-tests.el | 295 ++++++++++++++++++ 3 files changed, 347 insertions(+) create mode 100644 test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el index fec9d3c7ab8..09ccc001bdb 100644 --- a/lisp/net/dbus.el +++ b/lisp/net/dbus.el @@ -165,6 +165,9 @@ dbus-interface-local ;; </signal> ;; </interface> +(defconst dbus-annotation-deprecated (concat dbus-interface-dbus ".Deprecated") + "An annotation indicating a deprecated interface, method, signal, or property.") + \f ;;; Default D-Bus errors. diff --git a/test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml b/test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml new file mode 100644 index 00000000000..620f10510f2 --- /dev/null +++ b/test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml @@ -0,0 +1,49 @@ +<?xml version="1.0"?> +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.freedesktop.DBus.Introspectable"> + <method name="Introspect"> + <arg name="xml" type="s" direction="out"/> + </method> + </interface> + <interface name="org.freedesktop.DBus.Properties"> + <method name="Get"> + <arg name="interface" type="s" direction="in"/> + <arg name="name" type="s" direction="in"/> + <arg name="value" type="v" direction="out"/> + </method> + <method name="Set"> + <arg name="interface" type="s" direction="in"/> + <arg name="name" type="s" direction="in"/> + <arg name="value" type="v" direction="in"/> + </method> + <method name="GetAll"> + <arg name="interface" type="s" direction="in"/> + <arg name="properties" type="a{sv}" direction="out"/> + </method> + <signal name="PropertiesChanged"> + <arg name="interface" type="s"/> + <arg name="changed_properties" type="a{sv}"/> + <arg name="invalidated_properties" type="as"/> + </signal> + </interface> + <interface name="org.gnu.Emacs.TestDBus.Interface"> + <method name="Connect"> + <arg name="uuid" type="s" direction="in"/> + <arg name="mode" type="y" direction="in"/> + <arg name="options" type="a{sv}" direction="in"/> + <arg name="interface" type="s" direction="out"/> + </method> + <method name="DeprecatedMethod0"> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </method> + <method name="DeprecatedMethod1"> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </method> + <property name="Connected" type="b" access="read"/> + <property name="Player" type="o" access="read"/> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </interface> + <node name="node0"/> + <node name="node1"/> +</node> diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index fcbb378b44f..28dcdd95c00 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -46,6 +46,13 @@ dbus--test-path (defconst dbus--test-interface "org.gnu.Emacs.TestDBus.Interface" "Test interface.") +(defvar dbus--tests-dir + (file-truename + (expand-file-name "dbus-resources" + (file-name-directory (or load-file-name + buffer-file-name)))) + "Directory containing introspection test data file.") + (defun dbus--test-availability (bus) "Test availability of D-Bus BUS." (should (dbus-list-names bus)) @@ -1414,6 +1421,294 @@ dbus-test06-property-types ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(defun dbus--test-introspect () + "Return test introspection string." + (when (string-equal dbus--test-path (dbus-event-path-name last-input-event)) + (with-temp-buffer + (insert-file (expand-file-name "org.gnu.Emacs.TestDBus.xml" dbus--tests-dir)) + (buffer-string)))) + +(defsubst dbus--test-validate-interface + (iface-name expected-properties expected-methods expected-signals + expected-annotations) + "Validate an interface definition for `dbus-test07-introspection'. +The argument IFACE-NAME is a string naming the interface to validate. +The arguments EXPECTED-PROPERTIES, EXPECTED-METHODS, EXPECTED-SIGNALS, and +EXPECTED-ANNOTATIONS represent the names of the interface's properties, +methods, signals, and annotations, respectively." + + (let ((interface + (dbus-introspect-get-interface + :session dbus--test-service dbus--test-path iface-name))) + (pcase-let ((`(interface ((name . ,name)) . ,rest) interface)) + (should + (string-equal name iface-name)) + (should + (string-equal name (dbus-introspect-get-attribute interface "name"))) + + (let (properties methods signals annotations) + (mapc (lambda (x) + (let ((name (dbus-introspect-get-attribute x "name"))) + (cond + ((eq 'property (car x)) (push name properties)) + ((eq 'method (car x)) (push name methods)) + ((eq 'signal (car x)) (push name signals)) + ((eq 'annotation (car x)) (push name annotations))))) + rest) + + (should + (equal + (nreverse properties) + expected-properties)) + (should + (equal + (nreverse methods) + expected-methods)) + (should + (equal + (nreverse signals) + expected-signals)) + (should + (equal + (nreverse annotations) + expected-annotations)))))) + +(defsubst dbus--test-validate-annotations (annotations expected-annotations) + "Validate a list of D-Bus ANNOTATIONS. +Ensure each string in EXPECTED-ANNOTATIONS names an element of ANNOTATIONS. +And ensure each ANNOTATIONS has a value attribute marked \"true\"." + (mapc + (lambda (annotation) + (let ((name (dbus-introspect-get-attribute annotation "name")) + (value (dbus-introspect-get-attribute annotation "value"))) + (should + (member name expected-annotations)) + (should + (equal value "true")))) + annotations)) + +(defsubst dbus--test-validate-property + (interface property-name expected-annotations &rest expected-args) + "Validate a property definition for `dbus-test07-introspection'. + +The argument INTERFACE is a string naming the interface owning PROPERTY-NAME. +The argument PROPERTY-NAME is a string naming the property to validate. +The arguments EXPECTED-ANNOTATIONS is a list of strings matching +the annotation names defined for the method or signal. +The argument EXPECTED-ARGS is a list of expected arguments for the property." + (let* ((property + (dbus-introspect-get-property + :session dbus--test-service dbus--test-path interface property-name)) + (name (dbus-introspect-get-attribute property "name")) + (type (dbus-introspect-get-attribute property "type")) + (access (dbus-introspect-get-attribute property "access")) + (expected (assoc-string name expected-args))) + (should expected) + + (should + (string-equal name property-name)) + + (should + (string-equal + (nth 0 expected) + name)) + + (should + (string-equal + (nth 1 expected) + type)) + + (should + (string-equal + (nth 2 expected) + access)))) + +(defsubst dbus--test-validate-m-or-s (tree expected-annotations expected-args) + "Validate a method or signal definition for `dbus-test07-introspection'. +The argument TREE is an sexp returned from either `dbus-introspect-get-method' +or `dbus-introspect-get-signal' +The arguments EXPECTED-ANNOTATIONS is a list of strings matching +the annotation names defined for the method or signal. +The argument EXPECTED-ARGS is a list of expected arguments for +the method or signal." + (let (args annotations) + (mapc (lambda (elem) + (let ((name (dbus-introspect-get-attribute elem "name"))) + (cond + ((eq 'arg (car elem)) (push elem args)) + ((eq 'annotation (car elem)) (push elem annotations))))) + tree) + (should + (equal + (nreverse args) + expected-args)) + (dbus--test-validate-annotations annotations expected-annotations))) + +(defsubst dbus--test-validate-signal + (interface signal-name expected-annotations &rest expected-args) + "Validate a signal definition for `dbus-test07-introspection'. + +The argument INTERFACE is a string naming the interface owning SIGNAL-NAME. +The argument SIGNAL-NAME is a string naming the signal to validate. +The arguments EXPECTED-ANNOTATIONS is a list of strings matching +the annotation names defined for the signal. +The argument EXPECTED-ARGS is a list of expected arguments for the signal." + (let ((signal + (dbus-introspect-get-signal + :session dbus--test-service dbus--test-path interface signal-name))) + (pcase-let ((`(signal ((name . ,name)) . ,rest) signal)) + (should + (string-equal name signal-name)) + (should + (string-equal name (dbus-introspect-get-attribute signal "name"))) + (dbus--test-validate-m-or-s rest expected-annotations expected-args)))) + + +(defsubst dbus--test-validate-method + (interface method-name expected-annotations &rest expected-args) + "Validate a method definition for `dbus-test07-introspection'. + +The argument INTERFACE is a string naming the interface owning METHOD-NAME. +The argument METHOD-NAME is a string naming the method to validate. +The arguments EXPECTED-ANNOTATIONS is a list of strings matching +the annotation names defined for the method. +The argument EXPECTED-ARGS is a list of expected arguments for the method." + (let ((method + (dbus-introspect-get-method + :session dbus--test-service dbus--test-path interface method-name))) + (pcase-let ((`(method ((name . ,name)) . ,rest) method)) + (should + (string-equal name method-name)) + (should + (string-equal name (dbus-introspect-get-attribute method "name"))) + (dbus--test-validate-m-or-s rest expected-annotations expected-args)))) + +(ert-deftest dbus-test07-introspection () + "Register an Introspection interface then query it." + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + ;; Prepare introspection response. + (dbus-register-method + :session dbus--test-service dbus--test-path dbus-interface-introspectable + "Introspect" 'dbus--test-introspect) + (dbus-register-method + :session dbus--test-service (concat dbus--test-path "/node0") + dbus-interface-introspectable + "Introspect" 'dbus--test-introspect) + (dbus-register-method + :session dbus--test-service (concat dbus--test-path "/node1") + dbus-interface-introspectable + "Introspect" 'dbus--test-introspect) + (unwind-protect + (let ((start (current-time))) + ;; dbus-introspect-get-node-names + (should + (equal + (dbus-introspect-get-node-names + :session dbus--test-service dbus--test-path) + '("node0" "node1"))) + + ;; dbus-introspect-get-all-nodes + (should + (equal + (dbus-introspect-get-all-nodes + :session dbus--test-service dbus--test-path) + (list dbus--test-path + (concat dbus--test-path "/node0") + (concat dbus--test-path "/node1")))) + + ;; dbus-introspect-get-interface-names + (let ((interfaces + (dbus-introspect-get-interface-names + :session dbus--test-service dbus--test-path))) + + (should + (equal + interfaces + `(,dbus-interface-introspectable + ,dbus-interface-properties + ,dbus--test-interface))) + + (dbus--test-validate-interface + dbus-interface-introspectable nil '("Introspect") nil nil) + + ;; dbus-introspect-get-interface via `dbus--test-validate-interface' + (dbus--test-validate-interface + dbus-interface-properties nil + '("Get" "Set" "GetAll") '("PropertiesChanged") nil) + + (dbus--test-validate-interface + dbus--test-interface '("Connected" "Player") + '("Connect" "DeprecatedMethod0" "DeprecatedMethod1") nil + `(,dbus-annotation-deprecated))) + + ;; dbus-introspect-get-method-names + (let ((methods + (dbus-introspect-get-method-names + :session dbus--test-service dbus--test-path + dbus--test-interface))) + (should + (equal + methods + '("Connect" "DeprecatedMethod0" "DeprecatedMethod1"))) + + ;; dbus-introspect-get-method via 'dbus--test-validate-method + (dbus--test-validate-method + dbus--test-interface "Connect" nil + '(arg ((name . "uuid") (type . "s") (direction . "in"))) + '(arg ((name . "mode") (type . "y") (direction . "in"))) + '(arg ((name . "options") (type . "a{sv}") (direction . "in"))) + '(arg ((name . "interface") (type . "s") (direction . "out")))) + + (dbus--test-validate-method + dbus--test-interface "DeprecatedMethod0" + `(,dbus-annotation-deprecated)) + + (dbus--test-validate-method + dbus--test-interface "DeprecatedMethod1" + `(,dbus-annotation-deprecated))) + + ;; dbus-introspect-get-signal-names + (let ((signals + (dbus-introspect-get-signal-names + :session dbus--test-service dbus--test-path + dbus-interface-properties))) + (should + (equal + signals + '("PropertiesChanged"))) + + ;; dbus-introspect-get-signal via 'dbus--test-validate-signal + (dbus--test-validate-signal + dbus-interface-properties "PropertiesChanged" nil + '(arg ((name . "interface") (type . "s"))) + '(arg ((name . "changed_properties") (type . "a{sv}"))) + '(arg ((name . "invalidated_properties") (type . "as"))))) + + ;; dbus-intropct-get-property-names + (let ((properties + (dbus-introspect-get-property-names + :session dbus--test-service dbus--test-path + dbus--test-interface))) + (should + (equal + properties + '("Connected" "Player"))) + + ;; dbus-introspect-get-property via 'dbus--test-validate-property + (dbus--test-validate-property + dbus--test-interface "Connected" nil + '("Connected" "b" "read") + '("Player" "o" "read"))) + + ;; Elapsed time over a second suggests timeouts. + (should + (< 0.0 (float-time (time-since start)) 1.0))) + + (dbus-unregister-service :session dbus--test-service))) + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") -- 2.28.0 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #4: Timeout Tests. --] [-- Type: text/x-patch, Size: 2473 bytes --] From 454a9f4505bde8068675dfdf58658f752f561729 Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Mon, 28 Sep 2020 12:44:34 -0700 Subject: [PATCH 3/4] Add D-Bus timeout tests. * test/lisp/net/dbus-tests.el: Add timeout tests. (dbus-test04-call-method-timeout, dbus-test07-introspection-timeout): New tests. --- test/lisp/net/dbus-tests.el | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 28dcdd95c00..308f22eb6cc 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -581,6 +581,28 @@ dbus-test04-register-method ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(ert-deftest dbus-test04-call-method-timeout () + "Verify `dbus-call-method' request timeout." + :tags '(:expensive-test) + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + (unwind-protect + (let ((start (current-time))) + ;; Test timeout override for method call. + (should-error + (dbus-call-method + :session dbus--test-service dbus--test-path + dbus-interface-introspectable "Introspect" :timeout 2500) + :type 'dbus-error) + + (should + (< 2.4 (float-time (time-since start)) 2.7))) + + (dbus-unregister-service :session dbus--test-service))) + + (defvar dbus--test-signal-received nil "Received signal value in `dbus--test-signal-handler'.") @@ -1709,6 +1731,22 @@ dbus-test07-introspection (dbus-unregister-service :session dbus--test-service))) +(ert-deftest dbus-test07-introspection-timeout () + "Verify introspection request timeouts." + :tags '(:expensive-test) + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + (unwind-protect + (let ((start (current-time))) + (dbus-introspect-xml :session dbus--test-service dbus--test-path) + ;; Introspection internal timeout is one second. + (should + (< 1.0 (float-time (time-since start))))) + + (dbus-unregister-service :session dbus--test-service))) + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") -- 2.28.0 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #5: Call method reentry test. --] [-- Type: text/x-patch, Size: 2127 bytes --] From 3dc9e44e2f10530ef2b20cc9f8c3851606905d5e Mon Sep 17 00:00:00 2001 From: Hugh Daschbach <hdasch@fastmail.com> Date: Mon, 28 Sep 2020 14:34:54 -0700 Subject: [PATCH 4/4] Add D-Bus method call reentry test. * test/lisp/net/dbus-tests.el (dbus--tests-method-reentry-handler): New defun. (dbus-test04-method-reentry): New test. --- test/lisp/net/dbus-tests.el | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 308f22eb6cc..339eaa7405d 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -581,6 +581,40 @@ dbus-test04-register-method ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(defun dbus--test-method-reentry-handler (&rest args) + "Method handler for `dbus-test04-method-reentry'." + (dbus-get-all-managed-objects :session dbus--test-service dbus--test-path) + 42) + +(ert-deftest dbus-test04-method-reentry () + "Check receiving method call while awaiting response. +Ensure that incoming method calls are handled when call to `dbus-call-method' +is in progress." + ;; Simulate application registration (Bug#43251) + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + + (unwind-protect + (let ((method "Rentry")) + (should + (equal + (dbus-register-method + :session dbus--test-service dbus--test-path + dbus--test-interface method #'dbus--test-method-reentry-handler) + `((:method :session ,dbus--test-interface ,method) + (,dbus--test-service ,dbus--test-path + dbus--test-method-reentry-handler)))) + + (should + (= + (dbus-call-method + :session dbus--test-service dbus--test-path + dbus--test-interface method) + 42))) + + ;; Cleanup. + (dbus-unregister-service :session dbus--test-service))) + (ert-deftest dbus-test04-call-method-timeout () "Verify `dbus-call-method' request timeout." :tags '(:expensive-test) -- 2.28.0 ^ permalink raw reply related [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-29 21:51 ` Hugh Daschbach @ 2020-09-30 9:34 ` Michael Albinus 2020-09-30 10:42 ` Michael Albinus 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-30 9:34 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Hugh Daschbach <hugh@ccss.com> writes: Hi Hugh, > Thanks. I received the FSF signed copyright document. So we should be > clear for submission. Yep. You're also on file now. > I've attached the four patches that we've been discussing: three for > bug#43252 and on for bug#43251. Thanks a lot! I've pushed them to master. If you have further submissions, just tell me. I will submit them in your name then. If you plan for regular submissions to Emacs, you might ask the Emacs maintainers (Eli Zaretskii, Lars Ingebrigtsen or John Wiegley) for write access on the git repo. > Thanks for your patience and guidance. > > Hugh Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-30 9:34 ` Michael Albinus @ 2020-09-30 10:42 ` Michael Albinus 2020-09-30 16:39 ` Hugh Daschbach 0 siblings, 1 reply; 52+ messages in thread From: Michael Albinus @ 2020-09-30 10:42 UTC (permalink / raw) To: Hugh Daschbach; +Cc: 43252 Michael Albinus <michael.albinus@gmx.de> writes: Hi Hugh, >> I've attached the four patches that we've been discussing: three for >> bug#43252 and on for bug#43251. > > Thanks a lot! I've pushed them to master. PS: I've pushed also a minor code cleanup, mainly triggered by compiler warnings. Best regards, Michael. ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-30 10:42 ` Michael Albinus @ 2020-09-30 16:39 ` Hugh Daschbach 0 siblings, 0 replies; 52+ messages in thread From: Hugh Daschbach @ 2020-09-30 16:39 UTC (permalink / raw) To: Michael Albinus; +Cc: 43252 Michael Albinus writes: > Michael Albinus <michael.albinus@gmx.de> writes: > > Hi Hugh, > >> >> Thanks a lot! I've pushed them to master. > > PS: I've pushed also a minor code cleanup, mainly triggered by compiler warnings. Thank you. I've reviewed your changes. I appreciate the stylistic changes. And will add a compile step to my list workflow. Thanks again. Hugh ^ permalink raw reply [flat|nested] 52+ messages in thread
* bug#43252: Fwd: bug#43252: 27.1; DBus properties lack type hints or overrides 2020-09-07 0:54 bug#43252: 27.1; DBus properties lack type hints or overrides Hugh Daschbach 2020-09-07 7:48 ` Michael Albinus @ 2020-09-10 8:00 ` Michael Albinus 1 sibling, 0 replies; 52+ messages in thread From: Michael Albinus @ 2020-09-10 8:00 UTC (permalink / raw) To: 43252 [-- Attachment #0: Type: message/rfc822, Size: 2581 bytes --] [-- Attachment #1.1: Type: text/plain, Size: 649 bytes --] Michael Albinus writes: > Hugh Daschbach <hugh@ccss.com> writes: > > Hi Hugh, > > Appended. And thanks for your offer! Thanks, Michael. I've sent the email requesting the paperwork. Will let you know when it's submitted. In the meantime, just to check that I'm on the right track, I've attached a failing test. Sadly, it's more than 15 lines. Feel free to test with it. For the moment, I'll only forward failing tests. Once the paperwork is finalized I'll send you whatever suite of tests I've managed to come up with by then. Just for the record, I'm testing master currently at d08568e6e92. Cheers, Hugh [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1.2: Failing test, registering a property with compound value. --] [-- Type: text/x-patch, Size: 1372 bytes --] diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 8b456c3551f..8b79f5ac201 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -520,6 +520,31 @@ dbus-test05-register-property-several-paths ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(ert-deftest dbus-test06-register-property-types () + "Check property type preservation for an own service." + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + + (unwind-protect + (let ((byte-array "ByteArray")) + (should + (equal + (dbus-register-property + :session dbus--test-service dbus--test-path + dbus--test-interface byte-array :read byte-array '(:array :byte 1 :byte 2 : byte 3)) + `((:property :session dbus--test-path ,byte-array) + (,dbus--test-service ,dbus--test-path)))) + (should + (string-equal + (dbus-get-property + :session dbus--test-service dbus--test-path + dbus--test-interface byte-array) + '(1 2 3)))) + + ;; Cleanup. + (dbus-unregister-service :session dbus--test-service))) + + (defun dbus-test-all (&optional interactive) "Run all tests for \\[dbus]." (interactive "p") ^ permalink raw reply related [flat|nested] 52+ messages in thread
end of thread, other threads:[~2020-09-30 16:39 UTC | newest] Thread overview: 52+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-09-07 0:54 bug#43252: 27.1; DBus properties lack type hints or overrides Hugh Daschbach 2020-09-07 7:48 ` Michael Albinus 2020-09-07 17:35 ` Hugh Daschbach 2020-09-07 18:00 ` Michael Albinus 2020-09-07 19:18 ` Hugh Daschbach 2020-09-08 14:36 ` Michael Albinus 2020-09-09 4:10 ` Hugh Daschbach 2020-09-09 4:25 ` Hugh Daschbach 2020-09-09 13:25 ` Michael Albinus 2020-09-09 16:12 ` Hugh Daschbach 2020-09-09 17:43 ` Michael Albinus [not found] ` <874ko6979w.fsf@gmx.de> [not found] ` <87v9gm9x9i.fsf@ccss.com> 2020-09-10 14:59 ` Michael Albinus 2020-09-10 16:57 ` Michael Albinus 2020-09-10 19:09 ` Hugh Daschbach 2020-09-11 8:46 ` Michael Albinus 2020-09-10 22:53 ` Hugh Daschbach 2020-09-11 9:57 ` Michael Albinus 2020-09-11 14:19 ` Michael Albinus 2020-09-15 4:05 ` Hugh Daschbach 2020-09-16 12:47 ` Michael Albinus 2020-09-16 22:23 ` Hugh Daschbach 2020-09-17 12:58 ` Michael Albinus 2020-09-17 18:42 ` Hugh Daschbach 2020-09-18 6:28 ` Hugh Daschbach 2020-09-18 9:55 ` Michael Albinus 2020-09-18 13:42 ` Michael Albinus 2020-09-18 15:50 ` Michael Albinus 2020-09-18 9:36 ` Michael Albinus 2020-09-19 3:32 ` Hugh Daschbach 2020-09-20 15:05 ` Michael Albinus 2020-09-21 11:50 ` Michael Albinus 2020-09-22 3:48 ` Hugh Daschbach 2020-09-22 16:09 ` Michael Albinus 2020-09-22 17:36 ` Michael Albinus 2020-09-23 3:30 ` Hugh Daschbach 2020-09-23 3:34 ` Hugh Daschbach 2020-09-23 7:44 ` Michael Albinus 2020-09-23 17:32 ` Michael Albinus 2020-09-24 3:02 ` Hugh Daschbach 2020-09-24 8:48 ` Michael Albinus 2020-09-25 4:16 ` Hugh Daschbach 2020-09-26 1:27 ` Hugh Daschbach 2020-09-26 9:51 ` Michael Albinus 2020-09-28 3:00 ` Hugh Daschbach 2020-09-28 12:55 ` Michael Albinus 2020-09-28 23:17 ` Hugh Daschbach 2020-09-29 12:22 ` Michael Albinus 2020-09-29 21:51 ` Hugh Daschbach 2020-09-30 9:34 ` Michael Albinus 2020-09-30 10:42 ` Michael Albinus 2020-09-30 16:39 ` Hugh Daschbach 2020-09-10 8:00 ` bug#43252: Fwd: " Michael Albinus
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).