func (srv *service) Forever(setup func() error) error { log.Printf("start service [%v]\n", os.Getpid()) props := properties.Clone() log.Println("properties:") for _, k := range props.Keys() { log.Println(" ", k, props.Get(k)) } err := setup() if err != nil { return err } log.Println("service setup successful") sigCh := make(chan os.Signal) signal.Notify(sigCh, os.Kill, os.Interrupt, syscall.SIGTERM) err = nil select { case <-sigCh: case err = <-registry.ErrorChannel(): } close(registry.DoneChannel()) registry.DoneWaitGroup().Wait() return err }
func TestSanity(t *testing.T) { registry.DefaultServiceRegistry = registry.NewServiceRegistry() port := "44554" props := properties.Clone() props.Set("rest.port", port) handler := func(w http.ResponseWriter, r *http.Request) error { w.Write([]byte("done")) return nil } routes := PathHandlers{ "/abc": MethodHandlers{ "GET": handler, }, } err := NewServer(props, routes) if err != nil { t.Fatalf("new server error %v", err.Error()) } clientWG := sync.WaitGroup{} clientWG.Add(1) go func() { defer clientWG.Done() address := fmt.Sprintf("http://127.0.0.1:%v/abc", port) client := &http.Client{} req, err := http.NewRequest("GET", address, nil) if err != nil { t.Errorf("new request error %v", err.Error()) return } resp, err := client.Do(req) if err != nil { t.Fatalf("response err %v", err.Error()) } defer resp.Body.Close() bytes, err := ioutil.ReadAll(resp.Body) if err != nil { t.Fatalf("response read all err %v", err.Error()) } if string(bytes) != "done" { t.Fatalf("invalid response %v", string(bytes)) } }() clientWG.Wait() close(registry.DoneChannel()) registry.DoneWaitGroup().Wait() }
func TestIdleStop(t *testing.T) { registry.DefaultServiceRegistry = registry.NewServiceRegistry() err := NewServer(properties.Clone(), PathHandlers{}) if err != nil { t.Fatalf("new server error %v", err.Error()) } close(registry.DoneChannel()) registry.DoneWaitGroup().Wait() }
func TestDelayShutdownOnInitialDelay(t *testing.T) { registry.DefaultServiceRegistry = registry.NewServiceRegistry() scheduler := NewFixedDelayScheduler(100*time.Millisecond, 100*time.Millisecond) scheduler.Schedule(func() error { time.Sleep(100 * time.Millisecond) return nil }) <-time.After(40 * time.Millisecond) close(registry.DoneChannel()) registry.DoneWaitGroup().Wait() }
func TestDelayTaskFailure(t *testing.T) { registry.DefaultServiceRegistry = registry.NewServiceRegistry() scheduler := NewFixedDelayScheduler(0, time.Second) scheduler.Schedule(func() error { return errors.New("asd") }) err := <-registry.ErrorChannel() close(registry.DoneChannel()) registry.DoneWaitGroup().Wait() if err.Error() != "asd" { t.Errorf("unexpected error %v", err.Error()) } }
func TestDelaySanity(t *testing.T) { registry.DefaultServiceRegistry = registry.NewServiceRegistry() scheduler := NewFixedDelayScheduler(0, 100*time.Millisecond) counter := int32(0) scheduler.Schedule(func() error { atomic.AddInt32(&counter, 1) time.Sleep(100 * time.Millisecond) return nil }) <-time.After(300 * time.Millisecond) v := atomic.LoadInt32(&counter) if v != 2 { t.Errorf("invalid counter %v", v) } close(registry.DoneChannel()) registry.DoneWaitGroup().Wait() }
func TestDeflateCompression(t *testing.T) { registry.DefaultServiceRegistry = registry.NewServiceRegistry() port := "44559" props := properties.Clone() props.Set("rest.port", port) props.Set("rest.compression", "true") handler := func(w http.ResponseWriter, r *http.Request) error { w.Write([]byte("done")) return nil } routes := PathHandlers{ "/compression": MethodHandlers{ "GET": handler, }, } err := NewServer(props, routes) if err != nil { t.Fatalf("new server error %v", err.Error()) } clientWG := sync.WaitGroup{} clientWG.Add(1) go func() { defer clientWG.Done() address := fmt.Sprintf("http://127.0.0.1:%v/compression", port) client := &http.Client{} req, err := http.NewRequest("GET", address, nil) if err != nil { t.Errorf("new request error %v", err.Error()) return } req.Header.Add("Accept-Encoding", "deflate,gzip") resp, err := client.Do(req) if err != nil { t.Fatalf("response err %v", err.Error()) } defer resp.Body.Close() encoding := resp.Header.Get(http.CanonicalHeaderKey("Content-Encoding")) if encoding != "deflate" { t.Fatalf("invalid response encoding %v", encoding) } bytes, err := ioutil.ReadAll(flate.NewReader(resp.Body)) if err != nil { t.Fatalf("response read all err %v", err.Error()) } if string(bytes) != "done" { t.Fatalf("invalid response %v", string(bytes)) } }() clientWG.Wait() close(registry.DoneChannel()) registry.DoneWaitGroup().Wait() }
func TestNilResponse(t *testing.T) { registry.DefaultServiceRegistry = registry.NewServiceRegistry() port := "44557" props := properties.Clone() props.Set("rest.port", port) handler := func(w http.ResponseWriter, r *http.Request) error { WriteResponse(w, nil, http.StatusConflict) return nil } routes := PathHandlers{ "/nil": MethodHandlers{ "GET": handler, }, } err := NewServer(props, routes) if err != nil { t.Fatalf("new server error %v", err.Error()) } clientWG := sync.WaitGroup{} clientWG.Add(1) go func() { defer clientWG.Done() address := fmt.Sprintf("http://127.0.0.1:%v/nil", port) client := &http.Client{} req, err := http.NewRequest("GET", address, nil) if err != nil { t.Fatalf("new request error %v", err.Error()) return } resp, err := client.Do(req) if err != nil { t.Fatalf("response err %v", err.Error()) } defer resp.Body.Close() if resp.StatusCode != http.StatusConflict { t.Fatalf("invalid response status code %v", resp.StatusCode) } var responseContent string err = json.NewDecoder(resp.Body).Decode(&responseContent) if err != nil { t.Fatalf("response decode error %v", err.Error()) } if responseContent != http.StatusText(http.StatusConflict) { t.Fatalf("invalid response %v", responseContent) } }() clientWG.Wait() close(registry.DoneChannel()) registry.DoneWaitGroup().Wait() }
func TestErrorInHandler(t *testing.T) { registry.DefaultServiceRegistry = registry.NewServiceRegistry() port := "44556" props := properties.Clone() props.Set("rest.port", port) errorMessage := "f951a2344b8349ac222f02b4646ad504efc759e9" handler := func(w http.ResponseWriter, r *http.Request) error { return errors.New(errorMessage) } routes := PathHandlers{ "/err": MethodHandlers{ "GET": handler, }, } err := NewServer(props, routes) if err != nil { t.Fatalf("new server error %v", err.Error()) } clientWG := sync.WaitGroup{} clientWG.Add(1) go func() { defer clientWG.Done() address := fmt.Sprintf("http://127.0.0.1:%v/err", port) client := &http.Client{} req, err := http.NewRequest("GET", address, nil) if err != nil { t.Fatalf("new request error %v", err.Error()) return } resp, err := client.Do(req) if err != nil { t.Fatalf("response err %v", err.Error()) } defer resp.Body.Close() if resp.StatusCode != http.StatusInternalServerError { t.Fatalf("invalid response status code %v", resp.StatusCode) } var responseContent string err = json.NewDecoder(resp.Body).Decode(&responseContent) if err != nil { t.Fatalf("response decode error %v", err.Error()) } if responseContent != errorMessage { t.Fatalf("invalid response %v", responseContent) } }() clientWG.Wait() close(registry.DoneChannel()) registry.DoneWaitGroup().Wait() }