Russ Cox | 7dcc652 | 2014-01-13 23:08:10 -0500 | [diff] [blame] | 1 | // Copyright 2014 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | package main |
| 6 | |
| 7 | import ( |
Russ Cox | 3e7d4f1 | 2014-11-16 20:52:45 -0500 | [diff] [blame] | 8 | "cmd/internal/goobj" |
Russ Cox | 7dcc652 | 2014-01-13 23:08:10 -0500 | [diff] [blame] | 9 | "reflect" |
| 10 | "strings" |
| 11 | "testing" |
| 12 | ) |
| 13 | |
| 14 | // Each test case is an object file, generated from a corresponding .s file. |
| 15 | // The symbols in the object file with a dead_ prefix are the ones that |
| 16 | // should be removed from the program. |
| 17 | var deadTests = []string{ |
| 18 | "testdata/dead.6", |
| 19 | } |
| 20 | |
| 21 | func TestDead(t *testing.T) { |
| 22 | for _, obj := range deadTests { |
| 23 | p := Prog{GOOS: "darwin", GOARCH: "amd64", StartSym: "start"} |
| 24 | p.omitRuntime = true |
| 25 | p.Error = func(s string) { t.Error(s) } |
| 26 | p.init() |
| 27 | p.scan(obj) |
| 28 | if p.NumError > 0 { |
| 29 | continue // already reported |
| 30 | } |
| 31 | origSyms := copyMap(p.Syms) |
| 32 | origMissing := copyMap(p.Missing) |
| 33 | origSymOrder := copySlice(p.SymOrder) |
| 34 | origPkgSyms := copySlice(p.Packages["main"].Syms) |
| 35 | p.dead() |
| 36 | checkDeadMap(t, obj, "p.Syms", origSyms, p.Syms) |
| 37 | checkDeadMap(t, obj, "p.Missing", origMissing, p.Missing) |
| 38 | checkDeadSlice(t, obj, "p.SymOrder", origSymOrder, p.SymOrder) |
| 39 | checkDeadSlice(t, obj, `p.Packages["main"].Syms`, origPkgSyms, p.Packages["main"].Syms) |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | func copyMap(m interface{}) interface{} { |
| 44 | v := reflect.ValueOf(m) |
| 45 | out := reflect.MakeMap(v.Type()) |
| 46 | for _, key := range v.MapKeys() { |
| 47 | out.SetMapIndex(key, v.MapIndex(key)) |
| 48 | } |
| 49 | return out.Interface() |
| 50 | } |
| 51 | |
| 52 | func checkDeadMap(t *testing.T, obj, name string, old, new interface{}) { |
| 53 | vold := reflect.ValueOf(old) |
| 54 | vnew := reflect.ValueOf(new) |
| 55 | for _, vid := range vold.MapKeys() { |
| 56 | id := vid.Interface().(goobj.SymID) |
| 57 | if strings.HasPrefix(id.Name, "dead_") { |
| 58 | if vnew.MapIndex(vid).IsValid() { |
| 59 | t.Errorf("%s: %s contains unnecessary symbol %s", obj, name, id) |
| 60 | } |
| 61 | } else { |
| 62 | if !vnew.MapIndex(vid).IsValid() { |
| 63 | t.Errorf("%s: %s is missing symbol %s", obj, name, id) |
| 64 | } |
| 65 | } |
| 66 | } |
| 67 | for _, vid := range vnew.MapKeys() { |
| 68 | id := vid.Interface().(goobj.SymID) |
| 69 | if !vold.MapIndex(vid).IsValid() { |
| 70 | t.Errorf("%s: %s contains unexpected symbol %s", obj, name, id) |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | func copySlice(x []*Sym) (out []*Sym) { |
| 76 | return append(out, x...) |
| 77 | } |
| 78 | |
| 79 | func checkDeadSlice(t *testing.T, obj, name string, old, new []*Sym) { |
| 80 | for i, s := range old { |
| 81 | if strings.HasPrefix(s.Name, "dead_") { |
| 82 | continue |
| 83 | } |
| 84 | if len(new) == 0 { |
| 85 | t.Errorf("%s: %s is missing symbol %s\nhave%v\nwant%v", obj, name, s, new, old[i:]) |
| 86 | return |
| 87 | } |
| 88 | if new[0].SymID != s.SymID { |
| 89 | t.Errorf("%s: %s is incorrect: have %s, want %s\nhave%v\nwant%v", obj, name, new[0].SymID, s.SymID, new, old[i:]) |
| 90 | return |
| 91 | } |
| 92 | new = new[1:] |
| 93 | } |
| 94 | if len(new) > 0 { |
Robert Hencke | d461348 | 2014-04-26 19:54:48 -0700 | [diff] [blame] | 95 | t.Errorf("%s: %s has unexpected symbols: %v", obj, name, new) |
Russ Cox | 7dcc652 | 2014-01-13 23:08:10 -0500 | [diff] [blame] | 96 | } |
| 97 | } |