github.com/annwntech/go-micro/v2@v2.9.5/web/service_test.go (about)

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