Пример #1
0
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")
		}
	}
}
Пример #2
0
func TestAccountHandlerGetAllRefresh(t *testing.T) {
	ctx, handler := NewTestHandler(t)
	defer ctx.Close()

	c := core.NewTestConfig(t)
	var ff gateway.FeedFactory = &gateway.AccountFeedFactory{AccountRefresh: c.AccountRefresh}
	WaitForFeed(t, ctx, &ff, 15*time.Second)

	nc := make(chan *core.Notification)
	ctx.N.Subscribe(nc)
	defer ctx.N.Unsubscribe(nc)

	go func() {
		req := test.MakeSimpleRequest("GET", "http://1.2.3.4/v1/accounts", nil)
		req.Header.Add("Cache-Control", "private; max-age=0")
		test.RunRequest(t, handler, req)
		// NB: This request will not return data, as there's no feed running.
		// Long timeouts avoided as the ctx.Close() closes the Notifier,
		// which in turn closes the RefreshIfNeeded listener.
	}()

outer:
	for {
		select {
		case msg := <-nc:
			if msg.Type == core.NtAccountRefresh {
				// controller requested an account refresh, like it should have
				break outer
			}
		case <-time.After(15 * time.Second):
			t.Fatal("controller didn't request update before timeout")
		}
	}
}
Пример #3
0
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)
}
Пример #4
0
// 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,
	}
}
Пример #5
0
func TestAccountHandlerGetAll(t *testing.T) {
	ctx, handler := NewTestHandler(t)
	defer ctx.Close()

	c := core.NewTestConfig(t)
	var ff gateway.FeedFactory = &gateway.AccountFeedFactory{AccountRefresh: c.AccountRefresh}
	WaitForFeed(t, ctx, &ff, 15*time.Second)

	recorded := test.RunRequest(t, handler, test.MakeSimpleRequest("GET", "http://1.2.3.4/v1/accounts", nil))
	recorded.CodeIs(http.StatusOK)
	recorded.ContentTypeIsJson()
	recorded.HeaderIs("Cache-Control", "private, max-age=60")
}
Пример #6
0
// 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
		}
	}
}
Пример #7
0
// 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
}
Пример #8
0
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()
}
Пример #9
0
func TestAccountHandlerGetLatest(t *testing.T) {
	ctx, handler := NewTestHandler(t)
	defer ctx.Close()

	c := core.NewTestConfig(t)
	var ff gateway.FeedFactory = &gateway.AccountFeedFactory{AccountRefresh: c.AccountRefresh}
	WaitForFeed(t, ctx, &ff, 15*time.Second)

	accountCode := ""
	row := ctx.DB.QueryRow("SELECT account_code FROM account LIMIT 1")
	if err := row.Scan(&accountCode); err != nil {
		t.Fatal(err)
	}

	url := fmt.Sprintf("http://1.2.3.4/v1/accounts/%s", accountCode)
	recorded := test.RunRequest(t, handler, test.MakeSimpleRequest("GET", url, nil))
	recorded.CodeIs(http.StatusSeeOther)
	target := recorded.Recorder.Header().Get("Location")

	recorded = test.RunRequest(t, handler, test.MakeSimpleRequest("GET", target, nil))
	recorded.CodeIs(http.StatusOK)
	recorded.ContentTypeIsJson()
	recorded.HeaderIs("Cache-Control", "private, max-age=31556926")
}
Пример #10
0
func TestAccountFeedInsertsDataOnStartup(t *testing.T) {
	c := core.NewTestConfig(t)
	var ff FeedFactory = &AccountFeedFactory{c.AccountRefresh}
	TestSimpleFeedInsertsDataOnStartup(t, &ff, "account_snapshot", 15*time.Second)
}
Пример #11
0
func TestAccountFeedPublishesDoneMessage(t *testing.T) {
	c := core.NewTestConfig(t)
	var ff FeedFactory = &AccountFeedFactory{c.AccountRefresh}
	TestSimpleFeedPublishesDoneMessage(t, &ff, 15*time.Second)
}
Пример #12
0
func TestAccountFeedHandlesNoEngine(t *testing.T) {
	c := core.NewTestConfig(t)
	var ff FeedFactory = &AccountFeedFactory{c.AccountRefresh}
	TestSimpleFeedHandlesNoEngine(t, &ff)
}
Пример #13
0
func TestAccountFeedHandlesEngineTermination(t *testing.T) {
	c := core.NewTestConfig(t)
	var ff FeedFactory = &AccountFeedFactory{c.AccountRefresh}
	TestSimpleFeedHandlesEngineTermination(t, &ff, 15*time.Second)
}