liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

test.fnl (8160B)


      1 (local { : database : event-loop : parse-event : parse-terms } (require :devout))
      2 (local { : view } (require :fennel))
      3 (local ll (require :lualinux))
      4 (import-macros { : expect : expect= } :anoia.assert)
      5 
      6 (var failed false)
      7 (fn fail [d msg] (set failed true) (print :FAIL d (.. "\n" msg)))
      8 
      9 (macro example [description & body]
     10   (if (. body 1)
     11       `(let [(ok?# err#) (xpcall (fn [] ,body) debug.traceback)]
     12          (if ok?#
     13              (print :PASS ,description)
     14              (fail ,description err#)))
     15       `(print :PENDING ,description)))
     16 
     17 (local sda-uevent
     18        "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
     19 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
     20 SUBSYSTEM=block
     21 MAJOR=8
     22 MINOR=0
     23 DEVNAME=sda
     24 DEVTYPE=disk
     25 DISKSEQ=2
     26 SEQNUM=1527")
     27 
     28 (local sdb1-insert
     29        "add@/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\0ACTION=add
     30 DEVPATH=/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
     31 SUBSYSTEM=block
     32 DEVNAME=/dev/sdb1
     33 DEVTYPE=partition
     34 DISKSEQ=33
     35 PARTN=1
     36 SEQNUM=82381
     37 MAJOR=8
     38 MINOR=17")
     39 
     40 (local sdb1-remove
     41        "remove@/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\0ACTION=remove
     42 DEVPATH=/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
     43 SUBSYSTEM=block
     44 DEVNAME=/dev/sdb1
     45 DEVTYPE=partition
     46 DISKSEQ=33
     47 PARTN=1
     48 SEQNUM=82386
     49 MAJOR=8
     50 MINOR=17")
     51 
     52 (example
     53  "I can parse an event"
     54  (let [e (parse-event sdb1-insert)]
     55    (expect= e.properties.seqnum "82381")
     56    (expect= e.properties.devname "/dev/sdb1")
     57    (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")
     58    (expect= e.action :add)
     59    (expect= e (parse-event (e:format)))))
     60 
     61 (example
     62  "An event can match against terms"
     63  (let [terms {:devname "foo" :partname "my-usbstick"}]
     64    (expect= (: (parse-event "add@/\0SEQNUM=1") :matches? terms) false)
     65    (expect= (: (parse-event "add@/\0DEVNAME=bill") :matches? terms) false)
     66    (expect= (: (parse-event "add@/\0DEVNAME=foo\nPARTNAME=my-usbstick") :matches? terms) true)
     67    (expect= (: (parse-event "add@/\0DEVNAME=foo\nPARTNAME=my-usbstick\nOTHERTHING=bar") :matches? terms) true)
     68    ))
     69 
     70 (example
     71  "given an empty database, searching it finds no entries"
     72  (let [db (database)]
     73    (expect= (db:find {:partname "boot"}) [])))
     74 
     75 (example
     76  "when I add a device, I can find it"
     77  (let [db (database)]
     78    (db:add sda-uevent)
     79    (let [[m & more] (db:find {:devname "sda"})]
     80      (expect= m.properties.devname "sda")
     81      (expect= m.properties.major "8")
     82      (expect= more []))))
     83 
     84 (example
     85  "when I add a device, I cannot find it with wrong terms"
     86  (let [db (database)]
     87    (db:add sda-uevent)
     88    (expect= (db:find {:devname "sdb"}) [])))
     89 
     90 (example
     91  "when I add a device, I can retrieve it by path"
     92  (let [db (database)]
     93    (db:add sda-uevent)
     94    (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")]
     95      (expect= m.properties.devname "sda")
     96      (expect= m.properties.major "8"))))
     97 
     98 (example
     99  "when I add and then remove a device, I cannot retrieve it by path"
    100  (let [db (database)]
    101    (db:add sdb1-insert)
    102    (db:add sdb1-remove)
    103    (expect= (db:at-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") nil)))
    104 
    105 (example
    106  "when I add and then remove a device, I cannot find it"
    107  (let [db (database)]
    108    (db:add sdb1-insert)
    109    (db:add sda-uevent)
    110    (db:add sdb1-remove)
    111    (expect= (db:find {:devname "/dev/sdb1"}) [])))
    112 
    113 (example
    114  "when I search on multiple terms it uses all of them"
    115  (let [db (database)]
    116    (db:add sda-uevent)
    117    (expect= (# (db:find {:devname "sda" :devtype "disk"})) 1)
    118    (expect= (# (db:find {:devname "sda" :devtype "dosk"})) 0)))
    119 
    120 (example
    121  "I can find a device with sysfs attributes"
    122  (let [db (database {:sys-path "./fixtures/sys"})
    123        path "/devices/pci0000:00/0000:00:14.0/usb1"
    124        e (.. "add@" path "\0ACTION=add\n"
    125              (with-open [f (io.open (.. "fixtures/sys" path "/uevent"))]
    126                (f:read "*a")))]
    127    (db:add e)
    128    (let [[m & more] (db:find {:devtype "usb_device" :attr {:idVendor "1d6b" }})]
    129      (expect= m.properties.driver "usb")
    130      (expect= m.properties.major "189")
    131      (expect= more []))
    132    (let [[m & more] (db:find {:devtype "usb_device" :attr {:idVendor "0000" }})]
    133      (expect (not m)))
    134    ))
    135 
    136 (example
    137  "I can find a device matching ancestor sysfs attributes"
    138  (let [db (database {:sys-path "./fixtures/sys"})
    139        path "/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.1"
    140        e (.. "add@" path "\0ACTION=add\n"
    141              (with-open [f (io.open (.. "fixtures/sys" path "/uevent"))]
    142                (f:read "*a")))]
    143    (db:add e)
    144    (let [[m & more] (db:find {:devtype "usb_interface"
    145                               :driver "uvcvideo"
    146                               :attrs {:idVendor "13d3"
    147                                       :manufacturer "Azurewave"
    148                                       }})]
    149      (expect= m.properties.driver "uvcvideo")
    150      (expect= m.properties.interface "14/2/0")
    151      (expect= more []))
    152 
    153    (let [[m & more] (db:find {:devtype "usb_interface"
    154                               :driver "uvcvideo"
    155                               :attrs {:idVendor "23d3"
    156                                       :manufacturer "Azurewave"
    157                                       }})]
    158      (expect (not m)))))
    159 
    160 ;;; tests for indices
    161 
    162 (example "when I add a device with $attributes major minor foo bar baz,
    163  it is added to indices for foo bar baz but not major minor")
    164 
    165 (example "a removed device can no longer be found by looking in any index")
    166 
    167 (example "when I query with multiple attributes, the search is performed using the most specific attribute"
    168          ;; (= the attribute whose
    169          ;;   value at this key has fewest elements)
    170          )
    171 
    172 ;;; tests for subscriptions
    173 
    174 (example
    175  "I can subscribe to some search terms and be notified of matching events"
    176  (let [db (database)
    177        received []
    178        subscriber (fn [e] (table.insert received e))]
    179    (db:subscribe :me subscriber {:devname "/dev/sdb1"})
    180    (db:add sdb1-insert)
    181    (db:add sda-uevent)
    182    (db:add sdb1-remove)
    183    (expect= (# received) 2)))
    184 
    185 (example
    186  "Subscribers get notifications of prior events for present devices"
    187  (let [db (database)
    188        received []
    189        subscriber (fn [e] (table.insert received e))]
    190    (db:add sdb1-insert)
    191    (db:add sda-uevent)
    192    (db:subscribe :me subscriber {:devname "/dev/sdb1"})
    193    (expect= (# received) 1)))
    194 
    195 (example
    196  "I can unsubscribe after subscribing"
    197  (let [db (database)
    198        received []
    199        subscriber (fn [e] (table.insert received e))]
    200    (db:subscribe :me subscriber {:devname "/dev/sdb1"})
    201    (db:unsubscribe :me)
    202    (db:add sdb1-insert)
    203    (db:add sda-uevent)
    204    (db:add sdb1-remove)
    205    (expect= (# received) 0)))
    206 
    207 
    208 ;;; test for event loop
    209 
    210 (example
    211  "I can register a fd with a callback"
    212  (let [loop (event-loop)
    213        cb #(print $1)]
    214    (loop:register 3 cb)
    215    (expect= (. (loop:_tbl) 3) cb)))
    216 
    217 (example
    218  "when the fd is ready, my callback is called"
    219  (let [loop (event-loop)]
    220    (var ran? false)
    221    (loop:register 3 #(set ran? true))
    222    (loop:feed {3 1})
    223    (expect= ran? true)
    224    ))
    225 
    226 (example
    227  "when the callback returns true it remains registered"
    228  (let [loop (event-loop)]
    229    (loop:register 3 #true)
    230    (loop:feed {3 1})
    231    (expect (. (loop:_tbl) 3))
    232    ))
    233 
    234 (fn new-fd []
    235   (ll.open "/dev/zero" 0 0x1ff))
    236 
    237 (example
    238  "when the callback returns false it is unregistered and the fd is closed"
    239  (let [loop (event-loop)
    240        fd (new-fd)]
    241    (expect (> fd 2))
    242    (loop:register 3 #false)
    243    (loop:feed {3 1})
    244    (expect (not (. (loop:_tbl) 3)))
    245    (assert (not (os.execute (string.format "test -e /dev/fd/%d" fd))))
    246    ))
    247 
    248 
    249 (example
    250  "parse terms from string"
    251  (expect= (parse-terms "foo=bar baz=quuz")
    252           {:foo "bar" :baz "quuz" :attr {} :attrs {}})
    253  (expect= (parse-terms "foo=bar attr.womble=0x1234")
    254            {:foo "bar" :attr {:womble "0x1234"} :attrs {}}))
    255 
    256 (if failed (os.exit 1) (print "OK"))