diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2021-02-07 13:29:53 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2021-02-08 21:15:33 +0100 |
| commit | 2bd9619f762176527aaf28fb26e4a08b614b55df (patch) | |
| tree | 0052c13acd1df5136305039887b0c89791546af5 /pkg/runtest/run.go | |
| parent | 31a5cb08390f7ae45c40c79345c4ce5d17ac66bf (diff) | |
pkg/runtest: check arch requirement early
Need to check arch requirement early as some programs
may fail to deserialize on some arches due to missing syscalls.
See discussion on #2380.
Also support negative arch requirements (-arch=amd64).
Diffstat (limited to 'pkg/runtest/run.go')
| -rw-r--r-- | pkg/runtest/run.go | 68 |
1 files changed, 44 insertions, 24 deletions
diff --git a/pkg/runtest/run.go b/pkg/runtest/run.go index 4d81e2b60..437970768 100644 --- a/pkg/runtest/run.go +++ b/pkg/runtest/run.go @@ -192,10 +192,13 @@ func progFileList(dir, filter string) ([]string, error) { } func (ctx *Context) generateFile(progs chan *RunRequest, sandboxes []string, cover []bool, filename string) error { - p, requires, results, err := ctx.parseProg(filename) + p, requires, results, err := parseProg(ctx.Target, ctx.Dir, filename) if err != nil { return err } + if p == nil { + return nil + } sysTarget := targets.Get(ctx.Target.OS, ctx.Target.Arch) nextSandbox: for _, sandbox := range sandboxes { @@ -210,10 +213,9 @@ nextSandbox: } } properties := map[string]bool{ - "manual": ctx.Tests != "", // "manual" tests run only if selected by the filter explicitly. - "arch=" + ctx.Target.Arch: true, - "sandbox=" + sandbox: true, - "littleendian": ctx.Target.LittleEndian, + "manual": ctx.Tests != "", // "manual" tests run only if selected by the filter explicitly. + "sandbox=" + sandbox: true, + "littleendian": ctx.Target.LittleEndian, } for _, threaded := range []bool{false, true} { name := name @@ -272,34 +274,21 @@ nextSandbox: return nil } -func (ctx *Context) parseProg(filename string) (*prog.Prog, map[string]bool, *ipc.ProgInfo, error) { - return parseProg(ctx.Target, ctx.Dir, filename) -} - func parseProg(target *prog.Target, dir, filename string) (*prog.Prog, map[string]bool, *ipc.ProgInfo, error) { data, err := ioutil.ReadFile(filepath.Join(dir, filename)) if err != nil { return nil, nil, nil, fmt.Errorf("failed to read %v: %v", filename, err) } + requires := parseRequires(data) + // Need to check arch requirement early as some programs + // may fail to deserialize on some arches due to missing syscalls. + if !checkArch(requires, target.Arch) { + return nil, nil, nil, nil + } p, err := target.Deserialize(data, prog.Strict) if err != nil { return nil, nil, nil, fmt.Errorf("failed to deserialize %v: %v", filename, err) } - requires := make(map[string]bool) - for _, comment := range p.Comments { - const prefix = "requires:" - if !strings.HasPrefix(comment, prefix) { - continue - } - for _, req := range strings.Fields(comment[len(prefix):]) { - positive := true - if req[0] == '-' { - positive = false - req = req[1:] - } - requires[req] = positive - } - } errnos := map[string]int{ "": 0, "EPERM": 1, @@ -339,6 +328,37 @@ func parseProg(target *prog.Target, dir, filename string) (*prog.Prog, map[strin return p, requires, info, nil } +func parseRequires(data []byte) map[string]bool { + requires := make(map[string]bool) + for s := bufio.NewScanner(bytes.NewReader(data)); s.Scan(); { + const prefix = "# requires:" + line := s.Text() + if !strings.HasPrefix(line, prefix) { + continue + } + for _, req := range strings.Fields(line[len(prefix):]) { + positive := true + if req[0] == '-' { + positive = false + req = req[1:] + } + requires[req] = positive + } + } + return requires +} + +func checkArch(requires map[string]bool, arch string) bool { + for req, positive := range requires { + const prefix = "arch=" + if strings.HasPrefix(req, prefix) && + arch != req[len(prefix):] == positive { + return false + } + } + return true +} + func (ctx *Context) produceTest(progs chan *RunRequest, req *RunRequest, name string, properties, requires map[string]bool, results *ipc.ProgInfo) { req.name = name |
