github.com/gramework/gramework@v1.8.1-0.20231027140105-82555c9057f5/test/gramework_test.go (about)

     1  // Copyright 2017-present Kirill Danshin and Gramework contributors
     2  // Copyright 2019-present Highload LTD (UK CN: 11893420)
     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  
    11  package test
    12  
    13  import (
    14  	"crypto/tls"
    15  	"fmt"
    16  	"io"
    17  	"net"
    18  	"net/http"
    19  	"reflect"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/gramework/gramework"
    24  	"github.com/gramework/gramework/x/testutils"
    25  )
    26  
    27  func TestGrameworkHTTP(t *testing.T) {
    28  	app := gramework.New()
    29  	const text = "test one two three"
    30  	var preCalled, mwCalled, postCalled, jsonOK bool
    31  	app.GET("/", text)
    32  	app.GET("/bytes", []byte(text))
    33  	app.GET("/float32", float32(len(text)))
    34  	app.GET("/dumb", func() {})
    35  	app.GET("/dumbWithErr", func() error { return nil })
    36  	app.GET("/json", func(ctx *gramework.Context) {
    37  		m := map[string]map[string]map[string]map[string]int{
    38  			"abc": {
    39  				"def": {
    40  					"ghk": {
    41  						"wtf": 42,
    42  					},
    43  				},
    44  			},
    45  		}
    46  		jsonOK = true
    47  
    48  		if err := ctx.JSON(m); err != nil {
    49  			jsonOK = false
    50  			ctx.Logger.Errorf("can't JSON(): %s", err)
    51  		}
    52  
    53  		if b, err := ctx.ToJSON(m); err == nil {
    54  			var m2 map[string]map[string]map[string]map[string]int
    55  			if _, err := ctx.UnJSONBytes(b, &m2); err != nil {
    56  				ctx.Logger.Errorf("can't unjson: %s", err)
    57  				jsonOK = false
    58  				return
    59  			}
    60  
    61  			b2, err := ctx.ToJSON(m2)
    62  			if err != nil {
    63  				ctx.Logger.Errorf("ToJSON returns error: %s", err)
    64  				jsonOK = false
    65  				return
    66  			}
    67  
    68  			if len(b2) != len(b) {
    69  				ctx.Logger.Errorf("len is not equals, got len(b2) = [%v], len(b) = [%v]", len(b2), len(b))
    70  				jsonOK = false
    71  				return
    72  			}
    73  
    74  			if !reflect.DeepEqual(b, b2) {
    75  				jsonOK = false
    76  				return
    77  			}
    78  		}
    79  	})
    80  
    81  	var err error
    82  	app.ServeFile("/sf", "./nanotime.s")
    83  	app.SPAIndex("./nanotime.s")
    84  	app.GET("/sdnc_static/dist/*static", app.ServeDirNoCache("./"))
    85  	app.GET("/sdncc_static/dist/*static", app.ServeDirNoCacheCustom("./", 0, false, false, []string{}))
    86  	app.MethodNotAllowed(func(ctx *gramework.Context) {
    87  		_, err = ctx.WriteString("GTFO")
    88  		errCheck(t, err)
    89  	})
    90  
    91  	err = app.UsePre(func() {
    92  		preCalled = true
    93  	})
    94  	errCheck(t, err)
    95  
    96  	err = app.UsePre(func(ctx *gramework.Context) {
    97  		ctx.CORS()
    98  	})
    99  	errCheck(t, err)
   100  
   101  	err = app.Use(func() {
   102  		mwCalled = true
   103  	})
   104  	errCheck(t, err)
   105  
   106  	err = app.UseAfterRequest(func() {
   107  		postCalled = true
   108  	})
   109  	errCheck(t, err)
   110  
   111  	port := 42069
   112  	bindAddr := fmt.Sprintf(":%d", port)
   113  	go func() {
   114  		var err error
   115  		for i := 0; i < 10; i++ {
   116  			err := app.ListenAndServe(bindAddr)
   117  			if err != nil {
   118  				port++
   119  				bindAddr = fmt.Sprintf(":%d", port)
   120  			}
   121  		}
   122  		if err != nil {
   123  			t.Error("after 10 retries, consistently getting errors while trying to ListenAndServe. Last known error: " + err.Error())
   124  		}
   125  	}()
   126  
   127  	time.Sleep(3 * time.Second)
   128  
   129  	resp, err := http.Get("http://127.0.0.1" + bindAddr)
   130  	if err != nil {
   131  		t.Fatalf("Gramework isn't working! Got error: %s", err)
   132  		t.FailNow()
   133  	}
   134  
   135  	body, err := io.ReadAll(resp.Body)
   136  	if err != nil {
   137  		t.Fatalf("Gramework isn't working! Can't read body: %s", err)
   138  		t.FailNow()
   139  	}
   140  
   141  	err = resp.Body.Close()
   142  	errCheck(t, err)
   143  
   144  	if string(body) != text {
   145  		t.Fatalf(
   146  			"Gramework returned unexpected body! Got %q, expected %q",
   147  			string(body),
   148  			text,
   149  		)
   150  		t.FailNow()
   151  	}
   152  
   153  	resp, err = http.Get("http://127.0.0.1" + bindAddr + "/json")
   154  	if err != nil {
   155  		t.Fatalf("Gramework isn't working! Got error: %s", err)
   156  		t.FailNow()
   157  	}
   158  
   159  	_, err = io.ReadAll(resp.Body)
   160  	errCheck(t, err)
   161  
   162  	err = resp.Body.Close()
   163  	errCheck(t, err)
   164  
   165  	switch {
   166  	case !preCalled:
   167  		t.Fatalf("pre wasn't called")
   168  		t.FailNow()
   169  	case !mwCalled:
   170  		t.Fatalf("middleware wasn't called")
   171  		t.FailNow()
   172  	case !postCalled:
   173  		t.Fatalf("post middleware wasn't called")
   174  		t.FailNow()
   175  	case !jsonOK:
   176  		t.Fatalf("json response isn't OK")
   177  		t.FailNow()
   178  	}
   179  }
   180  
   181  func TestGrameworkDomainHTTP(t *testing.T) {
   182  	app := gramework.New()
   183  	const text = "test one two three"
   184  
   185  	ln, err := net.Listen("tcp", ":0")
   186  	if err != nil {
   187  		t.Fatal(err)
   188  	}
   189  
   190  	_, port, _ := net.SplitHostPort(ln.Addr().String())
   191  	bindAddr := fmt.Sprintf(":%s", port)
   192  
   193  	app.Domain("127.0.0.1"+bindAddr).GET("/", text)
   194  	var preCalled, mwCalled, postCalled bool
   195  
   196  	err = app.UsePre(func() {
   197  		preCalled = true
   198  	})
   199  	errCheck(t, err)
   200  
   201  	err = app.Use(func() {
   202  		mwCalled = true
   203  	})
   204  	errCheck(t, err)
   205  
   206  	err = app.UseAfterRequest(func() {
   207  		postCalled = true
   208  	})
   209  	errCheck(t, err)
   210  
   211  	go func() {
   212  		serveErr := app.Serve(ln)
   213  		errCheck(t, serveErr)
   214  	}()
   215  
   216  	time.Sleep(1 * time.Second)
   217  
   218  	resp, err := http.Get("http://127.0.0.1" + bindAddr)
   219  	if err != nil {
   220  		t.Fatalf("Gramework isn't working! Got error: %s", err)
   221  	}
   222  
   223  	body, err := io.ReadAll(resp.Body)
   224  	if err != nil {
   225  		t.Fatalf("Gramework isn't working! Can't read body: %s", err)
   226  	}
   227  
   228  	err = resp.Body.Close()
   229  	errCheck(t, err)
   230  
   231  	if string(body) != text {
   232  		t.Fatalf(
   233  			"Gramework returned unexpected body! Got %q, expected %q",
   234  			string(body),
   235  			text,
   236  		)
   237  	}
   238  
   239  	if !preCalled {
   240  		t.Fatalf("pre wasn't called")
   241  	}
   242  	if !mwCalled {
   243  		t.Fatalf("middleware wasn't called")
   244  	}
   245  	if !postCalled {
   246  		t.Fatalf("post middleware wasn't called")
   247  	}
   248  }
   249  
   250  func TestGrameworkHTTPS(t *testing.T) {
   251  	app := gramework.New()
   252  	const text = "test one two three"
   253  	app.GET("/", text)
   254  	app.TLSEmails = []string{"k@guava.by"}
   255  
   256  	ln, err := net.Listen("tcp", ":0")
   257  	if err != nil {
   258  		t.Fatal(err)
   259  	}
   260  
   261  	_, port, _ := net.SplitHostPort(ln.Addr().String())
   262  	bindAddr := fmt.Sprintf(":%s", port)
   263  
   264  	go func() {
   265  		err := app.ListenAndServeAutoTLS(bindAddr)
   266  		errCheck(t, err)
   267  	}()
   268  
   269  	time.Sleep(3 * time.Second)
   270  
   271  	tr := &http.Transport{
   272  		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   273  	}
   274  	client := &http.Client{Transport: tr}
   275  
   276  	resp, err := client.Get("https://127.0.0.1" + bindAddr)
   277  	if err != nil {
   278  		t.Fatalf("Gramework isn't working! Got error: %s", err)
   279  	}
   280  
   281  	body, err := io.ReadAll(resp.Body)
   282  	if err != nil {
   283  		t.Fatalf("Gramework isn't working! Can't read body: %s", err)
   284  	}
   285  
   286  	err = resp.Body.Close()
   287  	errCheck(t, err)
   288  
   289  	if string(body) != text {
   290  		t.Fatalf(
   291  			"Gramework returned unexpected body! Got %q, expected %q",
   292  			string(body),
   293  			text,
   294  		)
   295  	}
   296  }
   297  
   298  func TestGrameworkListenAll(t *testing.T) {
   299  	app := gramework.New()
   300  	const text = "test one two three"
   301  	app.GET("/", text)
   302  	app.TLSEmails = []string{"k@guava.by"}
   303  
   304  	port := 65356
   305  	bindAddr := fmt.Sprintf(":%d", port)
   306  	tlsPort := 65357
   307  	tlsBindAddr := fmt.Sprintf(":%d", tlsPort)
   308  	app.TLSPort = uint16(tlsPort)
   309  	go func() {
   310  		app.ListenAndServeAll(bindAddr)
   311  	}()
   312  
   313  	time.Sleep(3 * time.Second)
   314  
   315  	tr := &http.Transport{
   316  		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   317  	}
   318  	client := &http.Client{Transport: tr}
   319  
   320  	resp, err := client.Get("http://127.0.0.1" + bindAddr)
   321  	if err != nil {
   322  		t.Fatalf("Gramework isn't working! Got error: %s", err)
   323  	}
   324  
   325  	body, err := io.ReadAll(resp.Body)
   326  	if err != nil {
   327  		t.Fatalf("Gramework isn't working! Can't read body: %s", err)
   328  	}
   329  
   330  	err = resp.Body.Close()
   331  	errCheck(t, err)
   332  
   333  	if string(body) != text {
   334  		t.Fatalf(
   335  			"Gramework returned unexpected body! Got %q, expected %q",
   336  			string(body),
   337  			text,
   338  		)
   339  	}
   340  
   341  	resp, err = client.Get("https://127.0.0.1" + tlsBindAddr)
   342  	if err != nil {
   343  		t.Fatalf("Gramework isn't working! Got error: %s", err)
   344  	}
   345  
   346  	body, err = io.ReadAll(resp.Body)
   347  	if err != nil {
   348  		t.Fatalf("Gramework isn't working! Can't read body: %s", err)
   349  	}
   350  
   351  	err = resp.Body.Close()
   352  	errCheck(t, err)
   353  
   354  	if string(body) != text {
   355  		t.Fatalf(
   356  			"Gramework returned unexpected body! Got %q, expected %q",
   357  			string(body),
   358  			text,
   359  		)
   360  	}
   361  }
   362  
   363  func TestSPAIndexHandler(t *testing.T) {
   364  	app := gramework.New()
   365  	const text = "My Template"
   366  
   367  	app.SPAIndex(func(ctx *gramework.Context) {
   368  		_, err := ctx.WriteString(text)
   369  
   370  		if err != nil {
   371  			t.Fatalf("WriteString error: %s", err)
   372  			t.FailNow()
   373  		}
   374  	})
   375  
   376  	port := testutils.Port().NonRoot().Unused().Acquire()
   377  	bindAddr := fmt.Sprintf(":%d", port)
   378  	go func() {
   379  		listenErr := app.ListenAndServe(bindAddr)
   380  		errCheck(t, listenErr)
   381  	}()
   382  
   383  	time.Sleep(2 * time.Second)
   384  
   385  	resp, err := http.Get("http://127.0.0.1" + bindAddr)
   386  	if err != nil {
   387  		t.Fatalf("Gramework isn't working! Got error: %s", err)
   388  		t.FailNow()
   389  	}
   390  
   391  	body, err := io.ReadAll(resp.Body)
   392  	if err != nil {
   393  		t.Fatalf("Gramework isn't working! Can't read body: %s", err)
   394  		t.FailNow()
   395  	}
   396  
   397  	err = resp.Body.Close()
   398  	errCheck(t, err)
   399  
   400  	if string(body) != text {
   401  		t.Fatalf(
   402  			"Gramework returned unexpected body! Got %q, expected %q",
   403  			string(body),
   404  			text,
   405  		)
   406  		t.FailNow()
   407  	}
   408  
   409  	err = resp.Body.Close()
   410  	errCheck(t, err)
   411  }