-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdowntest.go
141 lines (130 loc) · 3.11 KB
/
downtest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright (c) 2013 Jason McVetta. This is Free Software, released under the
// terms of the GPL v3. See http://www.gnu.org/copyleft/gpl.html for details.
// Resist intellectual serfdom - the ownership of ideas is akin to slavery.
// Package downtest runs the tests on all downstream consumers of a package,
// as known to GoDoc.org.
package downtest
import (
"errors"
"fmt"
"github.com/jmcvetta/napping"
"os"
"os/exec"
"sort"
)
var apiUrl = "http://api.godoc.org/importers/"
// Import path of the downtest package - used to avoid having downtest
// run downtest's own tests.
const downtestPackage = "github.com/jmcvetta/downtest"
type importer struct {
Path string
Synopsis string
}
type apiResponse struct {
Results []importer
}
type apiError struct {
Error struct {
Message string
}
}
// A Package is a module of Go code identified by its import path.
type Package struct {
ImportPath string
Importers []string
Passed map[string]bool
Verbose bool
Update bool
}
// NewPackage prepares a package for downstream testing by looking up its
// importers.
func NewPackage(importPath string) (*Package, error) {
p := Package{
ImportPath: importPath,
}
err := p.LookupImporters()
if err != nil {
return &p, err
}
p.Passed = make(map[string]bool, len(p.Importers))
p.Update = true
return &p, nil
}
// LookupImporters gets the import paths of all downstream packages known by
// GoDoc.org to import this Package.
func (p *Package) LookupImporters() error {
url := apiUrl + p.ImportPath
var e apiError
var result apiResponse
var importers []string
req := napping.Request{
Url: url,
Method: "GET",
Result: &result,
Error: &e,
}
resp, err := napping.Send(&req)
if err != nil {
return err
}
if resp.Status() != 200 {
msg := fmt.Sprintf("Unexpected status from server: %d", resp.Status())
return errors.New(msg)
}
for _, r := range result.Results {
if r.Path == downtestPackage {
continue // Don't test self
}
importers = append(importers, r.Path)
}
sort.Strings(importers)
p.Importers = importers
return nil
}
// RunTests runs "go test" on downstream packages.
func (p *Package) RunTests() error {
for _, pkg := range p.Importers {
// 80 char witdth
// 4 char indent
// 2 char spacing
// 4 char status
// = 70 char padding
fmt.Printf(" %-73s", pkg)
p.Passed[pkg] = false
var c *exec.Cmd
if p.Update {
c = exec.Command("go", "get", "-u", "-v", pkg)
} else {
c = exec.Command("go", "get", "-v", pkg)
}
if p.Verbose {
fmt.Fprintln(os.Stderr, "+++ Running tests for", pkg, "+++")
fmt.Fprintln(os.Stderr)
fmt.Fprintln(os.Stderr, "> go get -v", pkg)
fmt.Fprintln(os.Stderr)
c.Stderr = os.Stderr
c.Stdout = os.Stderr
}
err := c.Run()
if err != nil {
fmt.Println("FAIL")
continue
}
c = exec.Command("go", "test", "-v", pkg)
if p.Verbose {
fmt.Fprintln(os.Stderr)
fmt.Fprintln(os.Stderr, "> go test -v", pkg)
fmt.Fprintln(os.Stderr)
c.Stderr = os.Stderr
c.Stdout = os.Stderr
}
err = c.Run()
if err != nil {
fmt.Println("FAIL")
continue
}
fmt.Println("pass")
p.Passed[pkg] = true
}
return nil
}