| // Copyright 2015 syzkaller project authors. All rights reserved. |
| // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. |
| |
| package csource |
| |
| import ( |
| "fmt" |
| "math/rand" |
| "os" |
| "strings" |
| "testing" |
| "time" |
| |
| "github.com/google/syzkaller/prog" |
| _ "github.com/google/syzkaller/sys" |
| ) |
| |
| func TestGenerate(t *testing.T) { |
| t.Parallel() |
| for _, target := range prog.AllTargets() { |
| switch target.OS { |
| case "netbsd", "windows": |
| continue |
| } |
| target := target |
| t.Run(target.OS+"/"+target.Arch, func(t *testing.T) { |
| if target.OS == "linux" && target.Arch == "arm" { |
| // This currently fails (at least with my arm-linux-gnueabihf-gcc-4.8) with: |
| // Assembler messages: |
| // Error: alignment too large: 15 assumed |
| t.Skip("broken") |
| } |
| if target.OS == "linux" && target.Arch == "386" { |
| // Currently fails on travis with: |
| // fatal error: asm/unistd.h: No such file or directory |
| t.Skip("broken") |
| } |
| if target.OS == "test" && target.PtrSize == 4 { |
| // The same reason as linux/32. |
| t.Skip("broken") |
| } |
| t.Parallel() |
| testTarget(t, target) |
| }) |
| } |
| } |
| |
| func testTarget(t *testing.T, target *prog.Target) { |
| seed := int64(time.Now().UnixNano()) |
| rs := rand.NewSource(seed) |
| t.Logf("seed=%v", seed) |
| r := rand.New(rs) |
| progs := []*prog.Prog{target.GenerateSimpleProg()} |
| if p := target.GenerateAllSyzProg(rs); len(p.Calls) != 0 { |
| progs = append(progs, p) |
| } |
| if !testing.Short() { |
| progs = append(progs, target.Generate(rs, 10, nil)) |
| } |
| opts := allOptionsSingle(target.OS) |
| opts = append(opts, Options{ |
| Threaded: true, |
| Collide: true, |
| Repeat: true, |
| Procs: 2, |
| Sandbox: "none", |
| Repro: true, |
| UseTmpDir: true, |
| }) |
| allPermutations := allOptionsPermutations(target.OS) |
| if testing.Short() { |
| for i := 0; i < 16; i++ { |
| opts = append(opts, allPermutations[r.Intn(len(allPermutations))]) |
| } |
| } else { |
| opts = allPermutations |
| } |
| for pi, p := range progs { |
| for opti, opts := range opts { |
| p, opts := p, opts |
| t.Run(fmt.Sprintf("%v/%v", pi, opti), func(t *testing.T) { |
| t.Parallel() |
| testOne(t, p, opts) |
| }) |
| } |
| } |
| } |
| |
| func testOne(t *testing.T, p *prog.Prog, opts Options) { |
| src, err := Write(p, opts) |
| if err != nil { |
| t.Logf("opts: %+v\nprogram:\n%s\n", opts, p.Serialize()) |
| t.Fatalf("%v", err) |
| } |
| bin, err := Build(p.Target, src) |
| if err != nil { |
| if strings.Contains(err.Error(), "no target compiler") { |
| t.Skip(err) |
| } |
| t.Logf("opts: %+v\nprogram:\n%s\n", opts, p.Serialize()) |
| t.Fatalf("%v", err) |
| } |
| defer os.Remove(bin) |
| } |