blob: eb34d0580d1889e486ee29c220d01b4f7c1b5c2b [file] [log] [blame]
Russ Cox7dcc6522014-01-13 23:08:10 -05001// 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
5package main
6
7import (
Russ Cox3e7d4f12014-11-16 20:52:45 -05008 "cmd/internal/goobj"
Russ Cox7dcc6522014-01-13 23:08:10 -05009 "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.
17var deadTests = []string{
18 "testdata/dead.6",
19}
20
21func 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
43func 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
52func 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
75func copySlice(x []*Sym) (out []*Sym) {
76 return append(out, x...)
77}
78
79func 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 Hencked4613482014-04-26 19:54:48 -070095 t.Errorf("%s: %s has unexpected symbols: %v", obj, name, new)
Russ Cox7dcc6522014-01-13 23:08:10 -050096 }
97}