move event matching tests to devout

in preparation for future uevent-watch not needing to do
event matching
This commit is contained in:
Daniel Barlow 2024-04-26 21:44:02 +01:00
parent bf0cafffed
commit 80628a3d90
3 changed files with 47 additions and 33 deletions

View file

@ -17,34 +17,38 @@
val# val# val# val#
(nil err#) (error (string.format "%s failed: errno=%d" ,(v expr) err#))))) (nil err#) (error (string.format "%s failed: errno=%d" ,(v expr) err#)))))
(fn parse-event [s]
(let [at (string.find s "@" 1 true)
(nl nxt) (string.find s "\0" 1 true)]
(doto
(collect [k v (string.gmatch
(string.sub s (+ 1 nxt))
"(%g-)=(%g+)")]
(k:lower) v)
(tset :path (string.sub s (+ at 1) (- nl 1))))))
(fn format-event [e] (fn format-event [e]
(.. (..
(string.format "%s@%s\0" e.action e.path) (string.format "%s@%s\0" e.action e.path)
(table.concat (table.concat
(icollect [k v (pairs e)] (icollect [k v (pairs e.attributes)]
(string.format "%s=%s" (string.upper k) v )) (string.format "%s=%s" (string.upper k) v ))
"\n"))) "\n")))
(fn event-matches? [e terms] (fn event-matches? [e terms]
(accumulate [match? true (accumulate [match? true
name value (pairs terms)] name value (pairs terms)]
(and match? (= value (. e name))))) (and match? (= value (. e.attributes name)))))
(fn parse-event [s]
(let [at (string.find s "@" 1 true)
(nl nxt) (string.find s "\0" 1 true)
attributes
(collect [k v (string.gmatch
(string.sub s (+ 1 nxt))
"(%g-)=(%g+)")]
(k:lower) v)]
{ : attributes
:path (string.sub s (+ at 1) (- nl 1))
:action (string.sub s 1 (- at 1))
:format format-event
:matches? event-matches?
}))
(fn find-in-database [db terms] (fn find-in-database [db terms]
(accumulate [found [] (accumulate [found []
_ e (pairs db)] _ e (pairs db)]
(if (event-matches? e terms) (if (e:matches? terms)
(doto found (table.insert e)) (doto found (table.insert e))
found))) found)))
@ -57,7 +61,7 @@
:remove (tset db e.path nil) :remove (tset db e.path nil)
) )
(each [_ { : terms : callback } (pairs subscribers)] (each [_ { : terms : callback } (pairs subscribers)]
(if (event-matches? e terms) (callback e))) (if (e:matches? terms) (callback e)))
e)) e))
(fn database [] (fn database []
@ -166,4 +170,4 @@
(ll.poll pollfds 5000) (ll.poll pollfds 5000)
(loop:feed (unpack-pollfds pollfds)))))) (loop:feed (unpack-pollfds pollfds))))))
{ : database : run : event-loop } { : database : run : event-loop : parse-event }

View file

@ -1,4 +1,4 @@
(local { : database : event-loop } (require :devout)) (local { : database : event-loop : parse-event } (require :devout))
(local { : view } (require :fennel)) (local { : view } (require :fennel))
(local ll (require :lualinux)) (local ll (require :lualinux))
(import-macros { : expect : expect= } :anoia.assert) (import-macros { : expect : expect= } :anoia.assert)
@ -14,11 +14,6 @@
(fail ,description err#))) (fail ,description err#)))
`(print :PENDING ,description))) `(print :PENDING ,description)))
(example
"given an empty database, searching it finds no entries"
(let [db (database)]
(expect= (db:find {:partname "boot"}) [])))
(local sda-uevent (local sda-uevent
"add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda\0ACTION=add "add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda\0ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda
@ -54,14 +49,36 @@ SEQNUM=82386
MAJOR=8 MAJOR=8
MINOR=17") MINOR=17")
(example
"I can parse an event"
(let [e (parse-event sdb1-insert)]
(expect= e.attributes.seqnum "82381")
(expect= e.attributes.devname "/dev/sdb1")
(expect= e.path "/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0/host1/target1:0:0/1:0:0:0/block/sdb/sdb1")
(expect= e.action :add)
(expect= e (parse-event (e:format)))))
(example
"An event can match against terms"
(let [terms {:devname "foo" :partname "my-usbstick"}]
(expect= (: (parse-event "add@/\0SEQNUM=1") :matches? terms) false)
(expect= (: (parse-event "add@/\0DEVNAME=bill") :matches? terms) false)
(expect= (: (parse-event "add@/\0DEVNAME=foo\nPARTNAME=my-usbstick") :matches? terms) true)
(expect= (: (parse-event "add@/\0DEVNAME=foo\nPARTNAME=my-usbstick\nOTHERTHING=bar") :matches? terms) true)
))
(example
"given an empty database, searching it finds no entries"
(let [db (database)]
(expect= (db:find {:partname "boot"}) [])))
(example (example
"when I add a device, I can find it" "when I add a device, I can find it"
(let [db (database)] (let [db (database)]
(db:add sda-uevent) (db:add sda-uevent)
(let [[m & more] (db:find {:devname "sda"})] (let [[m & more] (db:find {:devname "sda"})]
(expect= m.devname "sda") (expect= m.attributes.devname "sda")
(expect= m.major "8") (expect= m.attributes.major "8")
(expect= more [])))) (expect= more []))))
(example (example
@ -75,8 +92,8 @@ MINOR=17")
(let [db (database)] (let [db (database)]
(db:add sda-uevent) (db:add sda-uevent)
(let [m (db:at-path "/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda")] (let [m (db:at-path "/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda")]
(expect= m.devname "sda") (expect= m.attributes.devname "sda")
(expect= m.major "8")))) (expect= m.attributes.major "8"))))
(example (example
"when I add and then remove a device, I cannot retrieve it by path" "when I add and then remove a device, I cannot retrieve it by path"

View file

@ -3,13 +3,6 @@
(local subject (require :watch)) (local subject (require :watch))
(let [params
{:matches {:devname "foo" :partname "my-usbstick"}}]
(expect= (subject.event-matches? params {}) false)
(expect= (subject.event-matches? params {:devname "bill"}) false)
(expect= (subject.event-matches? params {:devname "foo" :partname "my-usbstick"}) true)
(expect= (subject.event-matches? params {:devname "foo" :otherthing "bar" :partname "my-usbstick"}) true)
)
;; Events come from the netlink socket as an initial summary line ;; Events come from the netlink socket as an initial summary line