github.com/ActiveState/go@v0.0.0-20170614201249-0b81c023a722/src/cmd/api/goapi_test.go (about)

     1  // Copyright 2011 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  	"bytes"
     9  	"flag"
    10  	"fmt"
    11  	"go/build"
    12  	"io/ioutil"
    13  	"os"
    14  	"os/exec"
    15  	"path/filepath"
    16  	"sort"
    17  	"strings"
    18  	"testing"
    19  )
    20  
    21  var (
    22  	updateGolden = flag.Bool("updategolden", false, "update golden files")
    23  )
    24  
    25  func TestGolden(t *testing.T) {
    26  	td, err := os.Open("testdata/src/pkg")
    27  	if err != nil {
    28  		t.Fatal(err)
    29  	}
    30  	fis, err := td.Readdir(0)
    31  	if err != nil {
    32  		t.Fatal(err)
    33  	}
    34  	for _, fi := range fis {
    35  		if !fi.IsDir() {
    36  			continue
    37  		}
    38  
    39  		// TODO(gri) remove extra pkg directory eventually
    40  		goldenFile := filepath.Join("testdata", "src", "pkg", fi.Name(), "golden.txt")
    41  		w := NewWalker(nil, "testdata/src/pkg")
    42  		pkg, _ := w.Import(fi.Name())
    43  		w.export(pkg)
    44  
    45  		if *updateGolden {
    46  			os.Remove(goldenFile)
    47  			f, err := os.Create(goldenFile)
    48  			if err != nil {
    49  				t.Fatal(err)
    50  			}
    51  			for _, feat := range w.Features() {
    52  				fmt.Fprintf(f, "%s\n", feat)
    53  			}
    54  			f.Close()
    55  		}
    56  
    57  		bs, err := ioutil.ReadFile(goldenFile)
    58  		if err != nil {
    59  			t.Fatalf("opening golden.txt for package %q: %v", fi.Name(), err)
    60  		}
    61  		wanted := strings.Split(string(bs), "\n")
    62  		sort.Strings(wanted)
    63  		for _, feature := range wanted {
    64  			if feature == "" {
    65  				continue
    66  			}
    67  			_, ok := w.features[feature]
    68  			if !ok {
    69  				t.Errorf("package %s: missing feature %q", fi.Name(), feature)
    70  			}
    71  			delete(w.features, feature)
    72  		}
    73  
    74  		for _, feature := range w.Features() {
    75  			t.Errorf("package %s: extra feature not in golden file: %q", fi.Name(), feature)
    76  		}
    77  	}
    78  }
    79  
    80  func TestCompareAPI(t *testing.T) {
    81  	tests := []struct {
    82  		name                                    string
    83  		features, required, optional, exception []string
    84  		ok                                      bool   // want
    85  		out                                     string // want
    86  	}{
    87  		{
    88  			name:     "feature added",
    89  			features: []string{"A", "B", "C", "D", "E", "F"},
    90  			required: []string{"B", "D"},
    91  			ok:       true,
    92  			out:      "+A\n+C\n+E\n+F\n",
    93  		},
    94  		{
    95  			name:     "feature removed",
    96  			features: []string{"C", "A"},
    97  			required: []string{"A", "B", "C"},
    98  			ok:       false,
    99  			out:      "-B\n",
   100  		},
   101  		{
   102  			name:     "feature added then removed",
   103  			features: []string{"A", "C"},
   104  			optional: []string{"B"},
   105  			required: []string{"A", "C"},
   106  			ok:       true,
   107  			out:      "±B\n",
   108  		},
   109  		{
   110  			name:      "exception removal",
   111  			required:  []string{"A", "B", "C"},
   112  			features:  []string{"A", "C"},
   113  			exception: []string{"B"},
   114  			ok:        true,
   115  			out:       "",
   116  		},
   117  		{
   118  			// https://golang.org/issue/4303
   119  			name: "contexts reconverging",
   120  			required: []string{
   121  				"A",
   122  				"pkg syscall (darwin-386), type RawSockaddrInet6 struct",
   123  				"pkg syscall (darwin-amd64), type RawSockaddrInet6 struct",
   124  			},
   125  			features: []string{
   126  				"A",
   127  				"pkg syscall, type RawSockaddrInet6 struct",
   128  			},
   129  			ok:  true,
   130  			out: "+pkg syscall, type RawSockaddrInet6 struct\n",
   131  		},
   132  	}
   133  	for _, tt := range tests {
   134  		buf := new(bytes.Buffer)
   135  		gotok := compareAPI(buf, tt.features, tt.required, tt.optional, tt.exception, true)
   136  		if gotok != tt.ok {
   137  			t.Errorf("%s: ok = %v; want %v", tt.name, gotok, tt.ok)
   138  		}
   139  		if got := buf.String(); got != tt.out {
   140  			t.Errorf("%s: output differs\nGOT:\n%s\nWANT:\n%s", tt.name, got, tt.out)
   141  		}
   142  	}
   143  }
   144  
   145  func TestSkipInternal(t *testing.T) {
   146  	tests := []struct {
   147  		pkg  string
   148  		want bool
   149  	}{
   150  		{"net/http", true},
   151  		{"net/http/internal-foo", true},
   152  		{"net/http/internal", false},
   153  		{"net/http/internal/bar", false},
   154  		{"internal/foo", false},
   155  		{"internal", false},
   156  	}
   157  	for _, tt := range tests {
   158  		got := !internalPkg.MatchString(tt.pkg)
   159  		if got != tt.want {
   160  			t.Errorf("%s is internal = %v; want %v", tt.pkg, got, tt.want)
   161  		}
   162  	}
   163  }
   164  
   165  func BenchmarkAll(b *testing.B) {
   166  	stds, err := exec.Command("go", "list", "std").Output()
   167  	if err != nil {
   168  		b.Fatal(err)
   169  	}
   170  	b.ResetTimer()
   171  	pkgNames := strings.Fields(string(stds))
   172  
   173  	for _, c := range contexts {
   174  		c.Compiler = build.Default.Compiler
   175  	}
   176  
   177  	for i := 0; i < b.N; i++ {
   178  		for _, context := range contexts {
   179  			w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src"))
   180  			for _, name := range pkgNames {
   181  				if name != "unsafe" && !strings.HasPrefix(name, "cmd/") && !internalPkg.MatchString(name) {
   182  					pkg, _ := w.Import(name)
   183  					w.export(pkg)
   184  				}
   185  			}
   186  			w.Features()
   187  		}
   188  	}
   189  }