github.com/goplus/yap@v0.8.1/ytest/classfile.go (about) 1 /* 2 * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package ytest 18 19 import ( 20 "io" 21 "net/http" 22 "net/http/httptest" 23 "os" 24 "reflect" 25 "strings" 26 "testing" 27 28 "github.com/goplus/yap" 29 "github.com/goplus/yap/test" 30 "github.com/goplus/yap/test/logt" 31 "github.com/qiniu/x/mockhttp" 32 ) 33 34 const ( 35 GopPackage = "github.com/goplus/yap/test" 36 GopTestClass = true 37 ) 38 39 // ----------------------------------------------------------------------------- 40 41 type App struct { 42 hosts map[string]string 43 transport http.RoundTripper 44 } 45 46 func (p *App) initApp() *App { 47 p.hosts = make(map[string]string) 48 p.transport = http.DefaultTransport 49 return p 50 } 51 52 // Mock runs a YAP server by mockhttp. 53 func (p *App) Mock(host string, app yap.AppType) { 54 tr := mockhttp.NewTransport() 55 p.transport = tr 56 app.InitYap() 57 app.SetLAS(func(addr string, h http.Handler) error { 58 return tr.ListenAndServe(host, h) 59 }) 60 app.(interface{ Main() }).Main() 61 } 62 63 // TestServer runs a YAP server by httptest.Server. 64 func (p *App) TestServer(host string, app yap.AppType) { 65 app.InitYap() 66 app.SetLAS(func(addr string, h http.Handler) error { 67 svr := httptest.NewServer(h) 68 p.Host("http://"+host, svr.URL) 69 return nil 70 }) 71 app.(interface{ Main() }).Main() 72 } 73 74 // RunMock runs a HTTP server by mockhttp. 75 func (p *App) RunMock(host string, h http.Handler) { 76 tr := mockhttp.NewTransport() 77 p.transport = tr 78 tr.ListenAndServe(host, h) 79 } 80 81 // RunTestServer runs a HTTP server by httptest.Server. 82 func (p *App) RunTestServer(host string, h http.Handler) { 83 svr := httptest.NewServer(h) 84 p.Host("http://"+host, svr.URL) 85 } 86 87 // Gopt_App_TestMain is required by Go+ compiler as the TestMain entry of a YAP testing project. 88 func Gopt_App_TestMain(app interface{ initApp() *App }, m *testing.M) { 89 app.initApp() 90 if me, ok := app.(interface{ MainEntry() }); ok { 91 me.MainEntry() 92 } 93 os.Exit(m.Run()) 94 } 95 96 // Gopt_App_Main is required by Go+ compiler as the Main entry of a YAP testing project. 97 func Gopt_App_Main(app interface{ initApp() *App }, workers ...interface{ initCase(*App, CaseT) }) { 98 a := app.initApp() 99 if me, ok := app.(interface{ MainEntry() }); ok { 100 me.MainEntry() 101 } 102 t := logt.New() 103 for _, worker := range workers { 104 worker.initCase(a, t) 105 reflect.ValueOf(worker).Elem().Field(1).Set(reflect.ValueOf(app)) // (*worker).App = app 106 worker.(interface{ Main() }).Main() 107 } 108 } 109 110 // Host replaces a host into real. For example: 111 // 112 // host "https://example.com" "http://localhost:8080" 113 // host "http://example.com" "http://localhost:8888" 114 func (p *App) Host(host, real string) { 115 if !strings.HasPrefix(host, "http") { 116 test.Fatalf("invalid host `%s`: should start with http:// or https://\n", host) 117 } 118 p.hosts[host] = real 119 } 120 121 func (p *App) hostOf(url string) (host string, url2 string, ok bool) { 122 // http://host/xxx or https://host/xxx 123 var istart int 124 if strings.HasPrefix(url[4:], "://") { 125 istart = 7 126 } else if strings.HasPrefix(url[4:], "s://") { 127 istart = 8 128 } else { 129 return 130 } 131 132 next := url[istart:] 133 n := strings.IndexByte(next, '/') 134 if n < 1 { 135 return 136 } 137 138 host = next[:n] 139 portal, ok := p.hosts[url[:istart+n]] 140 if ok { 141 url2 = portal + url[istart+n:] 142 } 143 return 144 } 145 146 func (p *App) newRequest(method, url string, body io.Reader) (req *http.Request, err error) { 147 if host, url2, ok := p.hostOf(url); ok { 148 req, err = http.NewRequest(method, url2, body) 149 req.Host = host 150 return 151 } 152 return http.NewRequest(method, url, body) 153 } 154 155 // -----------------------------------------------------------------------------