Skip to content
This repository has been archived by the owner on Feb 28, 2019. It is now read-only.

Commit

Permalink
Add tests for route handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
m-sandusky committed Nov 7, 2017
1 parent 7a0294b commit 10cbb2a
Show file tree
Hide file tree
Showing 3 changed files with 256 additions and 15 deletions.
14 changes: 0 additions & 14 deletions r2/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,20 +123,6 @@ type r2Handler struct {
auth auth.HTTPAuthService
}

type routeFunc func(s *service, r *http.Request) (data interface{}, err error)

// TODO(sandusky) Wrap each route with this function.
func handleRoute(rf routeFunc, s *service, r *http.Request, namespace string) (interface{}, error) {
start := s.nowFn()
data, err := rf(s, r)
dur := time.Since(start)
s.metrics.recordMetric(r.RequestURI, r.Method, namespace, dur, err)
if err != nil {
return nil, err
}
return data, nil
}

func (h r2Handler) wrap(fn r2HandlerFunc) http.Handler {
f := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := fn(w, r); err != nil {
Expand Down
15 changes: 14 additions & 1 deletion r2/service_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ package r2
import (
"fmt"
"net/http"
"time"

"github.com/gorilla/mux"
)

func fetchNamespaces(s *service, r *http.Request) (data interface{}, err error) {
func fetchNamespaces(s *service, _ *http.Request) (data interface{}, err error) {
view, err := s.store.FetchNamespaces()
if err != nil {
return nil, err
Expand Down Expand Up @@ -245,3 +246,15 @@ func fetchRollupRuleHistory(s *service, r *http.Request) (data interface{}, err
}
return newRollupRuleHistoryJSON(hist), nil
}

type routeFunc func(s *service, r *http.Request) (data interface{}, err error)

func handleRoute(rf routeFunc, s *service, r *http.Request, namespace string) (interface{}, error) {
start := s.nowFn()
data, err := rf(s, r)
s.metrics.recordMetric(r.RequestURI, r.Method, namespace, time.Since(start), err)
if err != nil {
return nil, err
}
return data, nil
}
242 changes: 242 additions & 0 deletions r2/service_routes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package r2

import (
"bytes"
"context"
"fmt"
"net/http"
"testing"

"github.com/m3db/m3ctl/auth"
"github.com/m3db/m3metrics/rules"
"github.com/m3db/m3x/clock"
"github.com/m3db/m3x/instrument"

"github.com/stretchr/testify/require"
)

func TestHandleRoute(t *testing.T) {
s := newTestService()
r := newTestGetRequest()
expected := newNamespacesJSON(&rules.NamespacesView{})
actual, err := handleRoute(fetchNamespaces, s, r, "ns")
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestFetchNamespaces_Success(t *testing.T) {
expected := newNamespacesJSON(&rules.NamespacesView{})
actual, err := fetchNamespaces(newTestService(), nil)
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestFetchNamespace_Success(t *testing.T) {
expected := newRuleSetJSON(&rules.RuleSetSnapshot{})
actual, err := fetchNamespace(newTestService(), newTestGetRequest())
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestCreateNamespace_Success(t *testing.T) {
expected := newNamespaceJSON(&rules.NamespaceView{})
actual, err := createNamespace(newTestService(), newTestPostRequest([]byte(`{"id": "id"}`)))
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestDeleteNamespace_Success(t *testing.T) {
expected := fmt.Sprintf("Deleted namespace %s", "")
actual, err := deleteNamespace(newTestService(), newTestDeleteRequest())
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestFetchMappingRule_Success(t *testing.T) {
expected := newMappingRuleJSON(&rules.MappingRuleView{})
actual, err := fetchMappingRule(newTestService(), newTestGetRequest())
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestCreateMappingRule_Success(t *testing.T) {
expected := newMappingRuleJSON(&rules.MappingRuleView{})
actual, err := createMappingRule(newTestService(), newTestPostRequest(
[]byte(`{"filter": "key:val", "name": "name", "policies": []}`),
))
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestUpdateMappingRule_Success(t *testing.T) {
expected := newMappingRuleJSON(&rules.MappingRuleView{})
actual, err := updateMappingRule(newTestService(), newTestPutRequest(
[]byte(`{"filter": "key:val", "name": "name", "policies": []}`),
))
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestDeleteMappingRule_Success(t *testing.T) {
expected := fmt.Sprintf("Deleted mapping rule: %s in namespace %s", "", "")
actual, err := deleteMappingRule(newTestService(), newTestDeleteRequest())
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestFetchMappingRuleHistory_Success(t *testing.T) {
expected := newMappingRuleHistoryJSON(make([]*rules.MappingRuleView, 0))
actual, err := fetchMappingRuleHistory(newTestService(), newTestGetRequest())
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestFetchRollupRule_Success(t *testing.T) {
expected := newRollupRuleJSON(&rules.RollupRuleView{})
actual, err := fetchRollupRule(newTestService(), newTestGetRequest())
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestCreateRollupRule_Success(t *testing.T) {
expected := newRollupRuleJSON(&rules.RollupRuleView{})
actual, err := createRollupRule(newTestService(), newTestPostRequest(
[]byte(`{"filter": "key:val", "name": "name", "targets": []}`),
))
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestUpdateRollupRule_Success(t *testing.T) {
expected := newRollupRuleJSON(&rules.RollupRuleView{})
actual, err := updateRollupRule(newTestService(), newTestPutRequest(
[]byte(`{"filter": "key:val", "name": "name", "targets": []}`),
))
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestDeleteRollupRule_Success(t *testing.T) {
expected := fmt.Sprintf("Deleted rollup rule: %s in namespace %s", "", "")
actual, err := deleteRollupRule(newTestService(), newTestDeleteRequest())
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func TestFetchRollupRuleHistory_Success(t *testing.T) {
expected := newRollupRuleHistoryJSON([]*rules.RollupRuleView{})
actual, err := fetchRollupRuleHistory(newTestService(), newTestGetRequest())
require.NoError(t, err)
require.Equal(t, expected, actual)
}

func newTestService() *service {
iOpts := instrument.NewOptions()
return &service{
metrics: newServiceMetrics(iOpts.MetricsScope()),
nowFn: clock.NewOptions().NowFn(),
store: newMockStore(),
authService: auth.NewNoopAuth(),
}
}

func newTestGetRequest() *http.Request {
req, _ := http.NewRequest("GET", "/route", nil)
return req.WithContext(context.Background())
}

func newTestPostRequest(bodyBuff []byte) *http.Request {
req, _ := http.NewRequest("POST", "/route", bytes.NewReader(bodyBuff))
return req.WithContext(context.Background())
}

func newTestPutRequest(bodyBuff []byte) *http.Request {
req, _ := http.NewRequest("PUT", "/route", bytes.NewReader(bodyBuff))
return req.WithContext(context.Background())
}

func newTestDeleteRequest() *http.Request {
req, _ := http.NewRequest("DELETE", "/route", nil)
return req.WithContext(context.Background())
}

type mockStore struct{}

func newMockStore() Store {
return mockStore{}
}

func (s mockStore) FetchNamespaces() (*rules.NamespacesView, error) {
return &rules.NamespacesView{}, nil
}

func (s mockStore) CreateNamespace(namespaceID string, uOpts UpdateOptions) (*rules.NamespaceView, error) {
return &rules.NamespaceView{}, nil
}

func (s mockStore) DeleteNamespace(namespaceID string, uOpts UpdateOptions) error {
return nil
}

func (s mockStore) FetchRuleSet(namespaceID string) (*rules.RuleSetSnapshot, error) {
return &rules.RuleSetSnapshot{}, nil
}

func (s mockStore) FetchMappingRule(namespaceID, mappingRuleID string) (*rules.MappingRuleView, error) {
return &rules.MappingRuleView{}, nil
}

func (s mockStore) CreateMappingRule(namespaceID string, mrv *rules.MappingRuleView, uOpts UpdateOptions) (*rules.MappingRuleView, error) {
return &rules.MappingRuleView{}, nil
}

func (s mockStore) UpdateMappingRule(namespaceID, mappingRuleID string, mrv *rules.MappingRuleView, uOpts UpdateOptions) (*rules.MappingRuleView, error) {
return &rules.MappingRuleView{}, nil
}

func (s mockStore) DeleteMappingRule(namespaceID, mappingRuleID string, uOpts UpdateOptions) error {
return nil
}

func (s mockStore) FetchMappingRuleHistory(namespaceID, mappingRuleID string) ([]*rules.MappingRuleView, error) {
return make([]*rules.MappingRuleView, 0), nil
}

func (s mockStore) FetchRollupRule(namespaceID, rollupRuleID string) (*rules.RollupRuleView, error) {
return &rules.RollupRuleView{}, nil
}

func (s mockStore) CreateRollupRule(namespaceID string, rrv *rules.RollupRuleView, uOpts UpdateOptions) (*rules.RollupRuleView, error) {
return &rules.RollupRuleView{}, nil
}

func (s mockStore) UpdateRollupRule(namespaceID, rollupRuleID string, rrv *rules.RollupRuleView, uOpts UpdateOptions) (*rules.RollupRuleView, error) {
return &rules.RollupRuleView{}, nil
}

func (s mockStore) DeleteRollupRule(namespaceID, rollupRuleID string, uOpts UpdateOptions) error {
return nil
}

func (s mockStore) FetchRollupRuleHistory(namespaceID, rollupRuleID string) ([]*rules.RollupRuleView, error) {
return make([]*rules.RollupRuleView, 0), nil
}

0 comments on commit 10cbb2a

Please sign in to comment.