Accessing udev from go

18 views
Skip to first unread message

val...@google.com

unread,
Dec 5, 2018, 5:24:12 PM12/5/18
to tast-users
I'm working on adding a new test using tast, and I'd like to add some support for udev. I looked into some open-source packages that had go bindings for C code, but I haven't had much success using any of them to make a proof-of-concept.

My need for udev is relatively straightforward, I'd like to my test to block until a device with a given vid/pid has been successfully connected on the system. I was able to write a simple C program that can verify if a device with the given vid/pid is present by calling into libudev directly. Is there any best practices for building a tast that uses some C code?

Daniel Erat

unread,
Dec 5, 2018, 6:21:55 PM12/5/18
to David Valleau, tast-...@chromium.org
I haven't used it before, but https://github.com/jochenvg/go-udev looks like a fairly thin wrapper that wraps libudev using Cgo. If it works, it'd be preferable to use it rather than wrapping your own C code that's specific to your test.

It's less efficient and hackier, but if you have some other way to check if the device is currently present (lsusb, lspci, sysfs, etc.), you could also using testing.Poll to wait for it to appear. I'd only recommend this if you aren't able to access udev via existing bindings, though.

On Wed, Dec 5, 2018 at 2:24 PM valleau via tast-users <tast-...@chromium.org> wrote:
I'm working on adding a new test using tast, and I'd like to add some support for udev. I looked into some open-source packages that had go bindings for C code, but I haven't had much success using any of them to make a proof-of-concept.

My need for udev is relatively straightforward, I'd like to my test to block until a device with a given vid/pid has been successfully connected on the system. I was able to write a simple C program that can verify if a device with the given vid/pid is present by calling into libudev directly. Is there any best practices for building a tast that uses some C code?

--
You received this message because you are subscribed to the Google Groups "tast-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tast-users+...@chromium.org.
To post to this group, send email to tast-...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/tast-users/bc41fba2-87c1-43f0-9276-704dad7a65ae%40chromium.org.

val...@google.com

unread,
Dec 5, 2018, 7:13:02 PM12/5/18
to tast-users, val...@google.com
Yeah that's the package I have been experimenting with. I've managed to get something working using the the Monitor type to poll for udev device events.

What are the guidelines for adding a package like this? I'm still very new to go, just went through the "tour' a few days ago.

Daniel Erat

unread,
Dec 5, 2018, 7:36:23 PM12/5/18
to David Valleau, tast-...@chromium.org
On Wed, Dec 5, 2018 at 4:13 PM valleau via tast-users <tast-...@chromium.org> wrote:
Yeah that's the package I have been experimenting with. I've managed to get something working using the the Monitor type to poll for udev device events.

What are the guidelines for adding a package like this? I'm still very new to go, just went through the "tour' a few days ago.

https://www.chromium.org/chromium-os/developer-guide/go-in-chromium-os contains some information about adding third-party packages. It's probably easier to look at recent commits that added packages under src/third_party/chromiumos-overlay/dev-go, though (e.g. check, selinux, yaml, etc.).
 
On Wednesday, December 5, 2018 at 3:21:55 PM UTC-8, Daniel Erat wrote:
I haven't used it before, but https://github.com/jochenvg/go-udev looks like a fairly thin wrapper that wraps libudev using Cgo. If it works, it'd be preferable to use it rather than wrapping your own C code that's specific to your test.

It's less efficient and hackier, but if you have some other way to check if the device is currently present (lsusb, lspci, sysfs, etc.), you could also using testing.Poll to wait for it to appear. I'd only recommend this if you aren't able to access udev via existing bindings, though.

On Wed, Dec 5, 2018 at 2:24 PM valleau via tast-users <tast-...@chromium.org> wrote:
I'm working on adding a new test using tast, and I'd like to add some support for udev. I looked into some open-source packages that had go bindings for C code, but I haven't had much success using any of them to make a proof-of-concept.

My need for udev is relatively straightforward, I'd like to my test to block until a device with a given vid/pid has been successfully connected on the system. I was able to write a simple C program that can verify if a device with the given vid/pid is present by calling into libudev directly. Is there any best practices for building a tast that uses some C code?

--
You received this message because you are subscribed to the Google Groups "tast-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tast-users+...@chromium.org.
To post to this group, send email to tast-...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/tast-users/bc41fba2-87c1-43f0-9276-704dad7a65ae%40chromium.org.

--
You received this message because you are subscribed to the Google Groups "tast-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tast-users+...@chromium.org.
To post to this group, send email to tast-...@chromium.org.

David Valleau

unread,
Dec 6, 2018, 5:58:25 PM12/6/18
to de...@chromium.org, tast-...@chromium.org
I've got the ebuilds set up and and working on getting my test running, but I'm having some issues actually building the test.

The "go-udev" package is failing to build because the "libudev.h" file is not found.

I tried explicitly emerging sys-fs/udev but I'm still getting the same error.
--
David Valleau

Daniel Erat

unread,
Dec 6, 2018, 6:05:02 PM12/6/18
to David Valleau, tast-...@chromium.org
Can you upload your in-progress ebuild change so I can take a look?

David Valleau

unread,
Dec 6, 2018, 6:18:41 PM12/6/18
to de...@chromium.org, tast-...@chromium.org

/*
  #cgo LDFLAGS: -ludev
  #include <libudev.h>            // Not found
  #include <linux/types.h>
  #include <stdlib.h>
#include <linux/kdev_t.h>
*/
import "C"

--
David Valleau

Daniel Erat

unread,
Dec 6, 2018, 6:23:35 PM12/6/18
to David Valleau, tast-...@chromium.org
Thanks, added a comment on the change. I suspect that the new package needs to depend on whichever package provides libudev.

David Valleau

unread,
Dec 6, 2018, 6:38:47 PM12/6/18
to de...@chromium.org, tast-...@chromium.org
I tried each of the suggested dependiences (sys-fs/udev, virtual/libudev, and virtual/udev) but I'm still seeing the same error.

Do you know where tast looks for the header to include? I checked /usr/include in my chroot and libudev.h is there.
--
David Valleau

Daniel Erat

unread,
Dec 6, 2018, 7:42:42 PM12/6/18
to David Valleau, tast-...@chromium.org
Ah, I see. I've summarized my understanding of the issue at https://crbug.com/912784, but it's tricky, and I don't see an obvious way to support Cgo within Tast tests or their dependencies. Maybe somebody else can think of something. :-/

Apologies for sending you on a wild goose chase with go-udev. As a hacky workaround for your particular use case, are you able to use testexec.CommandContext to run "udevadm monitor" to wait for your device, possibly with some combination of its -s and -t flags to filter the events that you receive?

David Valleau

unread,
Dec 6, 2018, 9:02:14 PM12/6/18
to de...@chromium.org, tast-...@chromium.org
It seems that udevadm monitor could be used to output the information I need for USB events.

The problem is that it writes it's output to stdout, and runs continuously with no option of providing a timeout. From what I can tell this means that testexec.CommandContext wouldn't work because it needs to wait until the process has completed before returning the output.

It looks like I could use the StdoutPipe function from os/exec in order to receive streaming output. Should I looking into building a wrapper for this into the testexec package?
--
David Valleau

Daniel Erat

unread,
Dec 6, 2018, 9:28:28 PM12/6/18
to David Valleau, tast-...@chromium.org
Note that testexec.Cmd embeds exec.Cmd, so everything present in the latter is also present in the former.

Here's some toy test code that looks for a line in a command's output:

package example

import (
    "bufio"
    "context"

    "chromiumos/tast/errors"
    "chromiumos/tast/local/testexec"
    "chromiumos/tast/testing"
)

func init() {
    testing.AddTest(&testing.Test{
        Func: WatchOutput,
        Desc: "Watches for output from a command",
        Attr: []string{"informational"},
    })
}

func WatchOutput(ctx context.Context, s *testing.State) {
    // Start a command that prints increasing integers, one per line.
    cmd := testexec.CommandContext(ctx,
        "sh", "-c", "for i in $(seq 0 100); do echo $i; sleep 1; done")
    p, err := cmd.StdoutPipe()
    if err != nil {
        s.Fatal("Failed to open pipe: ", err)
    }
    cmd.Start()
    defer cmd.Kill()

    // Start a goroutine that looks for a specific value and reports completion
    // (or an error) via a channel.
    const val = "5"
    ch := make(chan error, 1)
    go func() {
        sc := bufio.NewScanner(p)
        for sc.Scan() {
            if sc.Text() == "5" {
                s.Log("Got desired value: ", sc.Text())
                ch <- nil
                break
            } else {
                s.Log("Got some other value: ", sc.Text())
            }
        }
        if sc.Err() != nil {
            ch <- sc.Err()
        } else {
            ch <- errors.New("didn't find it")
        }
    }()

    // Wait for completion to be reported or for the test to time out.
    select {
    case err := <-ch:
        if err != nil {
            s.Error("Failed to read value: ", err)
        } else {
            s.Log("Read value successfully")
        }
    case <-ctx.Done():
        s.Error("Failed to get result: ", err)
    }
}

Reply all
Reply to author
Forward
0 new messages