github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/src/cmd/newlink/dead_test.go (about)

     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 (
     8  	"cmd/internal/goobj"
     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 {
    95  		t.Errorf("%s: %s has unexpected symbols: %v", obj, name, new)
    96  	}
    97  }