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  // -----------------------------------------------------------------------------