func TestControllerEngineUnavailable(t *testing.T) { c := core.NewTestConfig(t) c.IbGws = []string{"127.0.0.0:0000"} ctx, err := core.NewContext(c) if err != nil { t.Fatal(err) } defer ctx.Close() tcff := NewTestControllerFeedFactory(func(ctf *TestControllerFeed) { t.Fatal("Should never have opened feed") }) ffs := []FeedFactory{tcff} gatewayController, err := NewGatewayController(ffs, ctx.DB, ctx.N, ctx.DL, c.IbGws, c.IbClientId) if err != nil { t.Fatal(err) } defer gatewayController.Close() failAt := time.Now().Add(1 * time.Second) for gatewayController.Restarts() <= 5 { if time.Now().After(failAt) { t.Fatal("GatewayController failed to restart before timeout") } } }
func TestServiceCloseCanExecuteTwiceWithoutIssues(t *testing.T) { c := core.NewTestConfig(t) ctx, err := core.NewContext(c) if err != nil { t.Fatal(err) } defer ctx.Close() terminate := make(chan struct{}) errs := make(chan GatewayError) go func() { for { select { case <-errs: case <-terminate: return } } }() ffs := FeedFactories(c) ibGw := "127.0.0.0:0123" service := NewGatewayService(errs, ffs, ctx.DB, ctx.N, ibGw, c.IbClientId) service.Close() service.Close() close(terminate) }
// NewTestFeedContext provides a simple way of producing a FeedContext for tests. func NewTestFeedContext(t *testing.T) *TestFeedContext { c := core.NewTestConfig(t) ctx, err := core.NewContext(c) if err != nil { t.Fatal(err) } engine, err := ib.NewEngine(ib.NewEngineOptions{Gateway: c.IbGws[0]}) if err != nil { t.Fatal(err) } fc := &FeedContext{ Errors: make(chan FeedError), DB: ctx.DB, N: ctx.N, Eng: engine, } return &TestFeedContext{ ctx: ctx, FC: fc, } }
func main() { c, err := core.NewConfig() if err != nil { log.Fatal(err) } ctx, err := core.NewContext(c) if err != nil { log.Fatal(err) } defer ctx.Close() ffs := gateway.FeedFactories(c) gatewayController, err := gateway.NewGatewayController(ffs, ctx.DB, ctx.N, ctx.DL, c.IbGws, c.IbClientId) if err != nil { log.Fatal(err) } defer gatewayController.Close() terminated := handleSignals() handler := server.Handler(c.ErrInfo, ctx.DB, ctx.N) err = server.Serve(terminated, c.Address(), handler) if err != nil { log.Fatal(err) } // ensure we have terminated (useful if HTTP server commented out etc) <-terminated }
// runGatewayController executes the GatewayController, expecting the // TestControllerFeed to be created and closed the specified number of times // prior to the GatewayController being closed. func runGatewayController(t *testing.T, tcff *TestControllerFeedFactory, expectedOpens int, expectedCloses int) { c := core.NewTestConfig(t) ctx, err := core.NewContext(c) if err != nil { t.Fatal(err) } defer ctx.Close() ffs := []FeedFactory{tcff} gatewayController, err := NewGatewayController(ffs, ctx.DB, ctx.N, ctx.DL, c.IbGws, c.IbClientId) if err != nil { t.Fatal(err) } defer gatewayController.Close() terminating := false for { select { case ct := <-tcff.openClose: if ct[0] < expectedOpens { continue } if ct[1] < expectedCloses { continue } if !terminating && ct[0] > expectedOpens { t.Fatalf("too many opens (saw %d, expected %d)", ct[0], expectedOpens) } if !terminating && ct[1] > expectedCloses { t.Fatalf("too many closes (saw %d, expected %d)", ct[1], expectedCloses) } if !terminating { terminating = true gatewayController.Close() } if ct[0] == ct[1] { // enough events seen, and everything closed return } case <-time.After(1 * time.Second): t.Fatalf("timeout after %d opens (expected %d) and %d closes (expected %dd)", tcff.opened, expectedOpens, tcff.closed, expectedCloses) return } } }
// runGenericFeedTest returns any error reported to the error channel. It fails // the test if the expected count is not reached within one second of loading. func runGenericFeedTest(t *testing.T, fun func(*FeedContext), cronRefresh *cronexpr.Expression, waitTime time.Duration, expectedCount int) error { c := core.NewTestConfig(t) ctx, err := core.NewContext(c) if err != nil { t.Fatal(err) } defer ctx.Close() errors := make(chan FeedError) var lastError error terminateErrors := make(chan struct{}) defer close(terminateErrors) go func() { for { select { case e := <-errors: lastError = e.Error case <-terminateErrors: return } } }() var engine *ib.Engine fc := &FeedContext{errors, ctx.DB, ctx.N, engine} gft := newTestGenericFeed(t, fc, fun, cronRefresh) defer gft.Close() killAt := time.Now().Add(waitTime) for gft.counter < expectedCount { if lastError != nil { return lastError } if time.Now().After(killAt) { t.Fatal("Insufficient callbacks (%d) before timeout", gft.counter) } } gft.Close() return lastError }
func TestErrorHandlerInternalServerError(t *testing.T) { c := core.NewTestConfig(t) ctx, err := core.NewContext(c) if err != nil { t.Fatal(err) } defer ctx.Close() handler := Handler(true, ctx.DB, ctx.N) var ff gateway.FeedFactory = &gateway.AccountFeedFactory{AccountRefresh: c.AccountRefresh} WaitForFeed(t, ctx, &ff, 5*time.Second) ctx.DB.Close() // this will cause an internal server error recorded := test.RunRequest(t, handler, test.MakeSimpleRequest("GET", "http://1.2.3.4/v1/accounts", nil)) recorded.CodeIs(http.StatusInternalServerError) recorded.ContentTypeIsJson() }