-
Notifications
You must be signed in to change notification settings - Fork 0
/
json_test.go
139 lines (125 loc) · 3.94 KB
/
json_test.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
// Copyright Josh Komoroske. All rights reserved.
// Use of this source code is governed by the MIT license,
// a copy of which can be found in the LICENSE.txt file.
package meta
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
u "net/url"
"os"
"os/exec"
"strings"
"testing"
"time"
)
// info is a placeholder struct that only exists to store values from each
// public function in this package.
type info struct {
Arch string
Author string
AuthorEmail string
AuthorURL *u.URL
Copyright string
Date *time.Time
DateFormat string
Description string
Development bool
Docs *u.URL
Go string
License string
LicenseURL *u.URL
Name string
Note string
OS string
SHA string
ShortSHA string
Source *u.URL
Title string
URL *u.URL
Version string
VersionBuild string
VersionMajor string
VersionMinor string
VersionPatch string
VersionPreRelease string
}
// TestJSON serializes the placeholder info struct as JSON to stdout.
func TestJSON(t *testing.T) {
t.Parallel()
// Store a value from each public function in this package.
info := info{
Arch: Arch(),
Author: Author(),
AuthorEmail: AuthorEmail(),
AuthorURL: AuthorURL(),
Copyright: Copyright(),
Date: Date(),
DateFormat: DateFormat(time.RFC3339),
Description: Description(),
Development: Development(),
Docs: Docs(),
Go: Go(),
License: License(),
LicenseURL: LicenseURL(),
Name: Name(),
Note: Note(),
OS: OS(),
SHA: SHA(),
ShortSHA: ShortSHA(),
Source: Source(),
Title: Title(),
URL: URL(),
Version: Version(),
VersionBuild: VersionBuild(),
VersionMajor: VersionMajor(),
VersionMinor: VersionMinor(),
VersionPatch: VersionPatch(),
VersionPreRelease: VersionPreRelease(),
}
if err := json.NewEncoder(os.Stdout).Encode(info); err != nil {
t.Fatal(err)
}
}
// execTestJSON executes the specially crafted test TestJSON, by constructing a
// go test command line along with a custom set of ldflags. This causes the
// executed TestJSON test to react in a manner identical to a normal main()
// function. Including potential panic if an invalid ldflags value is passed.
// The TestJSON function marshals a single-line JSON string that contains a
// value for every public function in the package. This JSON string is searched
// for in the exec output, unmarshaled, and used in test assertions.
func execTestJSON(t *testing.T, args map[string]string) (*info, bool) {
t.Helper()
// Dynamically construct a -ldflags command line argument list.
var ldflags string
for key, value := range args {
ldflags += fmt.Sprintf(`-X '%s=%s' `, key, value)
}
// Construct a go test command line.
output, err := exec.Command("go", "test", "-ldflags", ldflags, "-test.run", "^TestJSON$", "-test.v", ".").Output() //nolint:gosec,lll
if err != nil {
// Error was not an exit error with the test program. Indicates an
// error with the test running setup itself.
if _, ok := err.(*exec.ExitError); !ok { //nolint:errorlint
t.Fatal(err)
}
// Program has a runtime error, but it was not a panic.
if !strings.HasPrefix(string(output), "panic:") {
t.Fatal(err)
}
// We failed...successfully!
return nil, true
}
scanner := bufio.NewScanner(bytes.NewBuffer(output))
for scanner.Scan() {
// Attempt to parse each line until we find one that is actually JSON.
var info info
if err := json.Unmarshal(scanner.Bytes(), &info); err == nil {
return &info, false
}
}
// None of the lines contained any JSON.
t.Fatal("no JSON could be parsed")
return nil, true
}