Skip to content

Commit e076851

Browse files
yookoalakazarena
authored andcommitted
Use mock network in testable examples
* Override http.DefaultTransport with a mock network if the environment variable `CI` is "true" (e.g. in Travis environment).
1 parent d6a87dc commit e076851

File tree

3 files changed

+4730
-0
lines changed

3 files changed

+4730
-0
lines changed

ld/example_test.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,150 @@ package ld_test
1616
import (
1717
"fmt"
1818
"log"
19+
"net/http"
20+
"os"
21+
"strings"
22+
"time"
1923

2024
"github.com/piprate/json-gold/ld"
2125
)
2226

27+
func init() {
28+
if os.Getenv("CI") == "true" {
29+
log.Print("mocking network in CI environment")
30+
mockTransport := make(muxRoundTripper)
31+
mockTransport.AddFunc("json-ld.org", mockJsonLdOrg)
32+
mockTransport.AddFunc("schema.org", mockSchemaOrg)
33+
mockTransport.Add("*", http.DefaultTransport) // as fallback
34+
http.DefaultTransport = mockTransport // override default transport
35+
}
36+
}
37+
38+
type roundTripFunc func(*http.Request) (*http.Response, error)
39+
40+
func (rt roundTripFunc) RoundTrip(r *http.Request) (*http.Response, error) {
41+
return rt(r)
42+
}
43+
44+
type muxRoundTripper map[string]http.RoundTripper
45+
46+
func (mux muxRoundTripper) Add(domain string, rt http.RoundTripper) {
47+
mux[domain] = rt
48+
}
49+
50+
func (mux muxRoundTripper) AddFunc(domain string, fn roundTripFunc) {
51+
mux[domain] = fn
52+
}
53+
54+
func (mux muxRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
55+
if tr, found := mux[r.URL.Host]; found {
56+
return tr.RoundTrip(r) // RoundTripper with match domain
57+
}
58+
if tr, found := mux["*"]; found {
59+
return tr.RoundTrip(r) // default RoundTripper
60+
}
61+
return nil, fmt.Errorf("no http.RoundTripper found for domain %s",
62+
r.URL.Host)
63+
}
64+
65+
func mockJsonLdOrg(r *http.Request) (resp *http.Response, err error) {
66+
if r.URL.Host != "json-ld.org" {
67+
err = fmt.Errorf("mock client only handle json-ld.org, not %s",
68+
r.URL.Host)
69+
return
70+
}
71+
if !strings.HasPrefix(r.URL.Path, "/test-suite/tests/") {
72+
err = fmt.Errorf("mock client only handle /test-suite/tests/*, not %s",
73+
r.URL.Path)
74+
return
75+
}
76+
path := strings.TrimPrefix(r.URL.Path, "/test-suite/tests/")
77+
f, err := os.Open("./testdata/" + path)
78+
if err != nil {
79+
return nil, fmt.Errorf("error openning testdata for mock transport: %s",
80+
err)
81+
}
82+
83+
s, err := f.Stat()
84+
if err != nil {
85+
return nil, fmt.Errorf("error getting file stat in mock transport: %s",
86+
err)
87+
}
88+
89+
// mock header
90+
header := make(http.Header)
91+
header.Add("Content-Length", fmt.Sprintf("%d", s.Size()))
92+
header.Add("Content-Type", "application/ld+json")
93+
header.Add("Date", s.ModTime().Format(time.RFC1123))
94+
95+
// mock response
96+
resp = &http.Response{
97+
Status: http.StatusText(http.StatusOK),
98+
StatusCode: http.StatusOK,
99+
Proto: r.Proto,
100+
ProtoMajor: r.ProtoMajor,
101+
ProtoMinor: r.ProtoMinor,
102+
ContentLength: s.Size(),
103+
Request: r,
104+
Header: header,
105+
Body: f,
106+
}
107+
return
108+
}
109+
110+
func mockSchemaOrg(r *http.Request) (resp *http.Response, err error) {
111+
if r.URL.Host != "schema.org" {
112+
err = fmt.Errorf("mock client only handle schema.org, not %s",
113+
r.URL.Host)
114+
return
115+
}
116+
117+
path := r.URL.Path
118+
if path == "/" {
119+
path = "/index.json"
120+
}
121+
122+
f, err := os.Open("./testdata/schema.org" + path)
123+
if err != nil {
124+
return nil, fmt.Errorf("error openning testdata for mock transport: %s",
125+
err)
126+
}
127+
128+
s, err := f.Stat()
129+
if err != nil {
130+
return nil, fmt.Errorf("error getting file stat in mock transport: %s",
131+
err)
132+
}
133+
134+
// mock header
135+
header := make(http.Header)
136+
header.Add("Content-Length", fmt.Sprintf("%d", s.Size()))
137+
header.Add("Content-Type", "application/ld+json")
138+
header.Add("Date", s.ModTime().Format(time.RFC1123))
139+
140+
// mock response
141+
resp = &http.Response{
142+
Status: http.StatusText(http.StatusOK),
143+
StatusCode: http.StatusOK,
144+
Proto: r.Proto,
145+
ProtoMajor: r.ProtoMajor,
146+
ProtoMinor: r.ProtoMinor,
147+
ContentLength: s.Size(),
148+
Request: r,
149+
Header: header,
150+
Body: f,
151+
}
152+
return
153+
}
154+
155+
func mockNetwork(options *ld.JsonLdOptions, transport roundTripFunc) *ld.JsonLdOptions {
156+
mockClient := &http.Client{
157+
Transport: transport,
158+
}
159+
options.DocumentLoader = ld.NewDefaultDocumentLoader(mockClient)
160+
return options
161+
}
162+
23163
func ExampleJsonLdProcessor_Expand_online() {
24164
proc := ld.NewJsonLdProcessor()
25165
options := ld.NewJsonLdOptions("")

0 commit comments

Comments
 (0)