mirror of https://github.com/golang/go.git
98 lines
2.6 KiB
Go
98 lines
2.6 KiB
Go
// Copyright 2014 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
import (
|
|
"debug/goobj"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// Each test case is an object file, generated from a corresponding .s file.
|
|
// The symbols in the object file with a dead_ prefix are the ones that
|
|
// should be removed from the program.
|
|
var deadTests = []string{
|
|
"testdata/dead.6",
|
|
}
|
|
|
|
func TestDead(t *testing.T) {
|
|
for _, obj := range deadTests {
|
|
p := Prog{GOOS: "darwin", GOARCH: "amd64", StartSym: "start"}
|
|
p.omitRuntime = true
|
|
p.Error = func(s string) { t.Error(s) }
|
|
p.init()
|
|
p.scan(obj)
|
|
if p.NumError > 0 {
|
|
continue // already reported
|
|
}
|
|
origSyms := copyMap(p.Syms)
|
|
origMissing := copyMap(p.Missing)
|
|
origSymOrder := copySlice(p.SymOrder)
|
|
origPkgSyms := copySlice(p.Packages["main"].Syms)
|
|
p.dead()
|
|
checkDeadMap(t, obj, "p.Syms", origSyms, p.Syms)
|
|
checkDeadMap(t, obj, "p.Missing", origMissing, p.Missing)
|
|
checkDeadSlice(t, obj, "p.SymOrder", origSymOrder, p.SymOrder)
|
|
checkDeadSlice(t, obj, `p.Packages["main"].Syms`, origPkgSyms, p.Packages["main"].Syms)
|
|
}
|
|
}
|
|
|
|
func copyMap(m interface{}) interface{} {
|
|
v := reflect.ValueOf(m)
|
|
out := reflect.MakeMap(v.Type())
|
|
for _, key := range v.MapKeys() {
|
|
out.SetMapIndex(key, v.MapIndex(key))
|
|
}
|
|
return out.Interface()
|
|
}
|
|
|
|
func checkDeadMap(t *testing.T, obj, name string, old, new interface{}) {
|
|
vold := reflect.ValueOf(old)
|
|
vnew := reflect.ValueOf(new)
|
|
for _, vid := range vold.MapKeys() {
|
|
id := vid.Interface().(goobj.SymID)
|
|
if strings.HasPrefix(id.Name, "dead_") {
|
|
if vnew.MapIndex(vid).IsValid() {
|
|
t.Errorf("%s: %s contains unnecessary symbol %s", obj, name, id)
|
|
}
|
|
} else {
|
|
if !vnew.MapIndex(vid).IsValid() {
|
|
t.Errorf("%s: %s is missing symbol %s", obj, name, id)
|
|
}
|
|
}
|
|
}
|
|
for _, vid := range vnew.MapKeys() {
|
|
id := vid.Interface().(goobj.SymID)
|
|
if !vold.MapIndex(vid).IsValid() {
|
|
t.Errorf("%s: %s contains unexpected symbol %s", obj, name, id)
|
|
}
|
|
}
|
|
}
|
|
|
|
func copySlice(x []*Sym) (out []*Sym) {
|
|
return append(out, x...)
|
|
}
|
|
|
|
func checkDeadSlice(t *testing.T, obj, name string, old, new []*Sym) {
|
|
for i, s := range old {
|
|
if strings.HasPrefix(s.Name, "dead_") {
|
|
continue
|
|
}
|
|
if len(new) == 0 {
|
|
t.Errorf("%s: %s is missing symbol %s\nhave%v\nwant%v", obj, name, s, new, old[i:])
|
|
return
|
|
}
|
|
if new[0].SymID != s.SymID {
|
|
t.Errorf("%s: %s is incorrect: have %s, want %s\nhave%v\nwant%v", obj, name, new[0].SymID, s.SymID, new, old[i:])
|
|
return
|
|
}
|
|
new = new[1:]
|
|
}
|
|
if len(new) > 0 {
|
|
t.Errorf("%s: %s has unexpected symbols: %v", new)
|
|
}
|
|
}
|