Package: emacs;
Reported by: Hugh Daschbach <hugh <at> ccss.com>
Date: Mon, 7 Sep 2020 00:55:02 UTC
Severity: normal
Found in version 27.1
Done: Michael Albinus <michael.albinus <at> gmx.de>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Hugh Daschbach <hugh <at> ccss.com> To: Michael Albinus <michael.albinus <at> gmx.de> Cc: 43252 <at> debbugs.gnu.org Subject: bug#43252: 27.1; DBus properties lack type hints or overrides Date: Fri, 18 Sep 2020 20:32:29 -0700
Michael Albinus writes: > Hugh Daschbach <hugh <at> 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
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.