github.com/go-graphite/carbonapi@v0.17.0/cmd/carbonapi/http/main_test.go (about)

     1  package http
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"math"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"testing"
    10  
    11  	"github.com/ansel1/merry"
    12  	"github.com/go-graphite/carbonapi/cmd/carbonapi/config"
    13  	"github.com/go-graphite/carbonapi/expr/types"
    14  	zipperTypes "github.com/go-graphite/carbonapi/zipper/types"
    15  	pb "github.com/go-graphite/protocol/carbonapi_v3_pb"
    16  	"github.com/lomik/zapwriter"
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  type mockCarbonZipper struct{}
    21  
    22  func newMockCarbonZipper() *mockCarbonZipper {
    23  	return new(mockCarbonZipper)
    24  }
    25  
    26  func (z mockCarbonZipper) Find(ctx context.Context, request pb.MultiGlobRequest) (*pb.MultiGlobResponse, *zipperTypes.Stats, merry.Error) {
    27  	return getGlobResponse(), nil, nil
    28  }
    29  
    30  func (z mockCarbonZipper) Info(ctx context.Context, metrics []string) (*pb.ZipperInfoResponse, *zipperTypes.Stats, merry.Error) {
    31  	response := getMockInfoResponse()
    32  
    33  	return response, nil, nil
    34  }
    35  
    36  func (z mockCarbonZipper) Render(ctx context.Context, request pb.MultiFetchRequest) ([]*types.MetricData, *zipperTypes.Stats, merry.Error) {
    37  	return z.RenderCompat(ctx, []string{""}, 0, 0)
    38  }
    39  
    40  func (z mockCarbonZipper) RenderCompat(ctx context.Context, metrics []string, from, until int64) ([]*types.MetricData, *zipperTypes.Stats, merry.Error) {
    41  	var result []*types.MetricData
    42  	multiFetchResponse := getMultiFetchResponse()
    43  	result = append(result, &types.MetricData{FetchResponse: multiFetchResponse.Metrics[0]})
    44  	return result, nil, nil
    45  }
    46  
    47  func (z mockCarbonZipper) TagNames(ctx context.Context, query string, limit int64) ([]string, merry.Error) {
    48  	return []string{}, nil
    49  }
    50  
    51  func (z mockCarbonZipper) TagValues(ctx context.Context, query string, limit int64) ([]string, merry.Error) {
    52  	return []string{}, nil
    53  }
    54  
    55  func (z mockCarbonZipper) ScaleToCommonStep() bool {
    56  	return true
    57  }
    58  
    59  func getGlobResponse() *pb.MultiGlobResponse {
    60  	globMtach := pb.GlobMatch{Path: "foo.bar", IsLeaf: true}
    61  	var matches []pb.GlobMatch
    62  	matches = append(matches, globMtach)
    63  	globResponse := &pb.MultiGlobResponse{
    64  		Metrics: []pb.GlobResponse{
    65  			{
    66  				Name:    "foo.bar",
    67  				Matches: matches,
    68  			},
    69  		},
    70  	}
    71  	return globResponse
    72  }
    73  
    74  func getMultiFetchResponse() pb.MultiFetchResponse {
    75  	mfr := pb.FetchResponse{
    76  		Name:           "foo.bar",
    77  		PathExpression: "foo.bar",
    78  		StartTime:      1510913280,
    79  		StopTime:       1510913880,
    80  		StepTime:       60,
    81  		Values:         []float64{math.NaN(), 1510913759, 1510913818},
    82  	}
    83  
    84  	result := pb.MultiFetchResponse{Metrics: []pb.FetchResponse{mfr}}
    85  	return result
    86  }
    87  
    88  func getMockInfoResponse() *pb.ZipperInfoResponse {
    89  	r := pb.Retention{
    90  		SecondsPerPoint: 60,
    91  		NumberOfPoints:  43200,
    92  	}
    93  	decoded := &pb.ZipperInfoResponse{
    94  		Info: map[string]pb.MultiMetricsInfoResponse{
    95  			"http://127.0.0.1:8080": {
    96  				Metrics: []pb.MetricsInfoResponse{{
    97  					Name:              "foo.bar",
    98  					ConsolidationFunc: "average",
    99  					MaxRetention:      157680000,
   100  					XFilesFactor:      0.5,
   101  					Retentions:        []pb.Retention{r},
   102  				}},
   103  			},
   104  		},
   105  	}
   106  
   107  	return decoded
   108  }
   109  
   110  func init() {
   111  	cfg := config.DefaultLoggerConfig
   112  	cfg.Level = "debug"
   113  	zapwriter.ApplyConfig([]zapwriter.Config{cfg})
   114  	logger := zapwriter.Logger("main")
   115  
   116  	cfgFile := ""
   117  	config.SetUpViper(logger, &cfgFile, false, "CARBONAPI_")
   118  	config.Config.Upstreams.Backends = []string{"dummy"}
   119  	config.SetUpConfigUpstreams(logger)
   120  	config.SetUpConfig(logger, "(test)")
   121  	config.Config.SetZipper(newMockCarbonZipper())
   122  	emptyStringList := make([]string, 0)
   123  	InitHandlers(emptyStringList, emptyStringList)
   124  }
   125  
   126  func setUpRequest(t *testing.T, url string) (*http.Request, *httptest.ResponseRecorder) {
   127  	req, err := http.NewRequest("GET", url, nil)
   128  	if err != nil {
   129  		t.Fatal(err)
   130  	}
   131  
   132  	// We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response.
   133  	rr := httptest.NewRecorder()
   134  	return req, rr
   135  }
   136  
   137  func TestRenderHandler(t *testing.T) {
   138  	req, rr := setUpRequest(t, "/render/?target=fallbackSeries(foo.bar,foo.baz)&from=-10minutes&format=json")
   139  	renderHandler(rr, req)
   140  
   141  	expected := `[{"target":"foo.bar","datapoints":[[null,1510913280],[1510913759,1510913340],[1510913818,1510913400]],"tags":{}}]`
   142  
   143  	// Check the status code is what we expect.
   144  	r := assert.Equal(t, rr.Code, http.StatusOK, "HttpStatusCode should be 200 OK.")
   145  	if !r {
   146  		t.Error("HttpStatusCode should be 200 OK.")
   147  	}
   148  	r = assert.Equal(t, expected, rr.Body.String(), "Http response should be same.")
   149  	if !r {
   150  		t.Error("Http response should be same.")
   151  	}
   152  }
   153  
   154  func TestFindHandler(t *testing.T) {
   155  	req, rr := setUpRequest(t, "/metrics/find/?query=foo.bar&format=json")
   156  	findHandler(rr, req)
   157  
   158  	body := rr.Body.String()
   159  	expected := `[{"allowChildren":0,"expandable":0,"leaf":1,"id":"foo.bar","text":"bar","context":{}}]` + "\n"
   160  	r := assert.Equal(t, rr.Code, http.StatusOK, "HttpStatusCode should be 200 OK.")
   161  	if !r {
   162  		t.Error("HttpStatusCode should be 200 OK.")
   163  	}
   164  	r = assert.Equal(t, expected, body, "Http response should be same.")
   165  	if !r {
   166  		t.Error("Http response should be same.")
   167  	}
   168  }
   169  
   170  func TestInfoHandler(t *testing.T) {
   171  	req, rr := setUpRequest(t, "/info/?target=foo.bar&format=json")
   172  	infoHandler(rr, req)
   173  
   174  	body := rr.Body.String()
   175  	expected := getMockInfoResponse()
   176  	expectedJson, err := json.Marshal(expected)
   177  	r := assert.Nil(t, err)
   178  	if !r {
   179  		t.Errorf("err should be nil, %v instead", err)
   180  	}
   181  
   182  	r = assert.Equal(t, rr.Code, http.StatusOK, "HttpStatusCode should be 200 OK.")
   183  	if !r {
   184  		t.Error("Http response should be same.")
   185  	}
   186  	r = assert.Equal(t, string(expectedJson), body, "Http response should be same.")
   187  	if !r {
   188  		t.Error("Http response should be same.")
   189  	}
   190  }