gitee.com/sasukebo/go-micro/v4@v4.7.1/web/service_test.go (about)

     1  package web
     2  
     3  import (
     4  	"crypto/tls"
     5  	"fmt"
     6  	"io"
     7  	"net/http"
     8  	"os"
     9  	"os/signal"
    10  	"syscall"
    11  	"testing"
    12  	"time"
    13  
    14  	"gitee.com/sasukebo/go-micro/v4/registry"
    15  )
    16  
    17  func TestService(t *testing.T) {
    18  	var (
    19  		beforeStartCalled bool
    20  		afterStartCalled  bool
    21  		beforeStopCalled  bool
    22  		afterStopCalled   bool
    23  		str               = `<html><body><h1>Hello World</h1></body></html>`
    24  		fn                = func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, str) }
    25  		reg               = registry.NewMemoryRegistry()
    26  	)
    27  
    28  	beforeStart := func() error {
    29  		beforeStartCalled = true
    30  		return nil
    31  	}
    32  
    33  	afterStart := func() error {
    34  		afterStartCalled = true
    35  		return nil
    36  	}
    37  
    38  	beforeStop := func() error {
    39  		beforeStopCalled = true
    40  		return nil
    41  	}
    42  
    43  	afterStop := func() error {
    44  		afterStopCalled = true
    45  		return nil
    46  	}
    47  
    48  	service := NewService(
    49  		Name("go.micro.web.test"),
    50  		Registry(reg),
    51  		BeforeStart(beforeStart),
    52  		AfterStart(afterStart),
    53  		BeforeStop(beforeStop),
    54  		AfterStop(afterStop),
    55  	)
    56  
    57  	service.HandleFunc("/", fn)
    58  
    59  	errCh := make(chan error, 1)
    60  	go func() {
    61  		errCh <- service.Run()
    62  		close(errCh)
    63  	}()
    64  
    65  	var s []*registry.Service
    66  
    67  	eventually(func() bool {
    68  		var err error
    69  		s, err = reg.GetService("go.micro.web.test")
    70  		return err == nil
    71  	}, t.Fatal)
    72  
    73  	if have, want := len(s), 1; have != want {
    74  		t.Fatalf("Expected %d but got %d services", want, have)
    75  	}
    76  
    77  	rsp, err := http.Get(fmt.Sprintf("http://%s", s[0].Nodes[0].Address))
    78  	if err != nil {
    79  		t.Fatal(err)
    80  	}
    81  	defer rsp.Body.Close()
    82  
    83  	b, err := io.ReadAll(rsp.Body)
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  
    88  	if string(b) != str {
    89  		t.Errorf("Expected %s got %s", str, string(b))
    90  	}
    91  
    92  	callbackTests := []struct {
    93  		subject string
    94  		have    interface{}
    95  	}{
    96  		{"beforeStartCalled", beforeStartCalled},
    97  		{"afterStartCalled", afterStartCalled},
    98  	}
    99  
   100  	for _, tt := range callbackTests {
   101  		if tt.have != true {
   102  			t.Errorf("unexpected %s: want true, have false", tt.subject)
   103  		}
   104  	}
   105  
   106  	select {
   107  	case err := <-errCh:
   108  		if err != nil {
   109  			t.Fatalf("service.Run():%v", err)
   110  		}
   111  	case <-time.After(time.Duration(time.Second)):
   112  		if len(os.Getenv("IN_TRAVIS_CI")) == 0 {
   113  			t.Logf("service.Run() survived a client request without an error")
   114  		}
   115  	}
   116  
   117  	ch := make(chan os.Signal, 1)
   118  	signal.Notify(ch, syscall.SIGTERM)
   119  	p, _ := os.FindProcess(os.Getpid())
   120  	p.Signal(syscall.SIGTERM)
   121  
   122  	<-ch
   123  
   124  	select {
   125  	case err := <-errCh:
   126  		if err != nil {
   127  			t.Fatalf("service.Run():%v", err)
   128  		} else {
   129  			if len(os.Getenv("IN_TRAVIS_CI")) == 0 {
   130  				t.Log("service.Run() nil return on syscall.SIGTERM")
   131  			}
   132  		}
   133  	case <-time.After(time.Duration(time.Second)):
   134  		if len(os.Getenv("IN_TRAVIS_CI")) == 0 {
   135  			t.Logf("service.Run() survived a client request without an error")
   136  		}
   137  	}
   138  
   139  	eventually(func() bool {
   140  		_, err := reg.GetService("go.micro.web.test")
   141  		return err == registry.ErrNotFound
   142  	}, t.Error)
   143  
   144  	callbackTests = []struct {
   145  		subject string
   146  		have    interface{}
   147  	}{
   148  		{"beforeStopCalled", beforeStopCalled},
   149  		{"afterStopCalled", afterStopCalled},
   150  	}
   151  
   152  	for _, tt := range callbackTests {
   153  		if tt.have != true {
   154  			t.Errorf("unexpected %s: want true, have false", tt.subject)
   155  		}
   156  	}
   157  
   158  }
   159  
   160  func TestOptions(t *testing.T) {
   161  	var (
   162  		name             = "service-name"
   163  		id               = "service-id"
   164  		version          = "service-version"
   165  		address          = "service-addr:8080"
   166  		advertise        = "service-adv:8080"
   167  		reg              = registry.NewMemoryRegistry()
   168  		registerTTL      = 123 * time.Second
   169  		registerInterval = 456 * time.Second
   170  		handler          = http.NewServeMux()
   171  		metadata         = map[string]string{"key": "val"}
   172  		secure           = true
   173  	)
   174  
   175  	service := NewService(
   176  		Name(name),
   177  		Id(id),
   178  		Version(version),
   179  		Address(address),
   180  		Advertise(advertise),
   181  		Registry(reg),
   182  		RegisterTTL(registerTTL),
   183  		RegisterInterval(registerInterval),
   184  		Handler(handler),
   185  		Metadata(metadata),
   186  		Secure(secure),
   187  	)
   188  
   189  	opts := service.Options()
   190  
   191  	tests := []struct {
   192  		subject string
   193  		want    interface{}
   194  		have    interface{}
   195  	}{
   196  		{"name", name, opts.Name},
   197  		{"version", version, opts.Version},
   198  		{"id", id, opts.Id},
   199  		{"address", address, opts.Address},
   200  		{"advertise", advertise, opts.Advertise},
   201  		{"registry", reg, opts.Registry},
   202  		{"registerTTL", registerTTL, opts.RegisterTTL},
   203  		{"registerInterval", registerInterval, opts.RegisterInterval},
   204  		{"handler", handler, opts.Handler},
   205  		{"metadata", metadata["key"], opts.Metadata["key"]},
   206  		{"secure", secure, opts.Secure},
   207  	}
   208  
   209  	for _, tc := range tests {
   210  		if tc.want != tc.have {
   211  			t.Errorf("unexpected %s: want %v, have %v", tc.subject, tc.want, tc.have)
   212  		}
   213  	}
   214  }
   215  
   216  func eventually(pass func() bool, fail func(...interface{})) {
   217  	tick := time.NewTicker(10 * time.Millisecond)
   218  	defer tick.Stop()
   219  
   220  	timeout := time.After(time.Second)
   221  
   222  	for {
   223  		select {
   224  		case <-timeout:
   225  			fail("timed out")
   226  			return
   227  		case <-tick.C:
   228  			if pass() {
   229  				return
   230  			}
   231  		}
   232  	}
   233  }
   234  
   235  func TestTLS(t *testing.T) {
   236  	var (
   237  		str    = `<html><body><h1>Hello World</h1></body></html>`
   238  		fn     = func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, str) }
   239  		secure = true
   240  		reg    = registry.NewMemoryRegistry()
   241  	)
   242  
   243  	service := NewService(
   244  		Name("go.micro.web.test"),
   245  		Secure(secure),
   246  		Registry(reg),
   247  	)
   248  
   249  	service.HandleFunc("/", fn)
   250  
   251  	errCh := make(chan error, 1)
   252  	go func() {
   253  		errCh <- service.Run()
   254  		close(errCh)
   255  	}()
   256  
   257  	var s []*registry.Service
   258  
   259  	eventually(func() bool {
   260  		var err error
   261  		s, err = reg.GetService("go.micro.web.test")
   262  		return err == nil
   263  	}, t.Fatal)
   264  
   265  	if have, want := len(s), 1; have != want {
   266  		t.Fatalf("Expected %d but got %d services", want, have)
   267  	}
   268  
   269  	tr := &http.Transport{
   270  		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   271  	}
   272  	client := &http.Client{Transport: tr}
   273  	rsp, err := client.Get(fmt.Sprintf("https://%s", s[0].Nodes[0].Address))
   274  	if err != nil {
   275  		t.Fatal(err)
   276  	}
   277  	defer rsp.Body.Close()
   278  
   279  	b, err := io.ReadAll(rsp.Body)
   280  	if err != nil {
   281  		t.Fatal(err)
   282  	}
   283  
   284  	if string(b) != str {
   285  		t.Errorf("Expected %s got %s", str, string(b))
   286  	}
   287  
   288  	select {
   289  	case err := <-errCh:
   290  		if err != nil {
   291  			t.Fatalf("service.Run():%v", err)
   292  		}
   293  	case <-time.After(time.Duration(time.Second)):
   294  		if len(os.Getenv("IN_TRAVIS_CI")) == 0 {
   295  			t.Logf("service.Run() survived a client request without an error")
   296  		}
   297  	}
   298  
   299  }