github.com/m3db/m3@v1.5.0/src/query/api/v1/handler/prometheus/native/parse_threshold_test.go (about)

     1  // Copyright (c) 2019 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package native
    22  
    23  import (
    24  	"fmt"
    25  	"io"
    26  	"io/ioutil"
    27  	"net/http/httptest"
    28  	"net/url"
    29  	"testing"
    30  
    31  	"github.com/m3db/m3/src/query/api/v1/options"
    32  	"github.com/m3db/m3/src/query/executor"
    33  	"github.com/m3db/m3/src/x/instrument"
    34  	xtest "github.com/m3db/m3/src/x/test"
    35  	pql "github.com/prometheus/prometheus/promql/parser"
    36  
    37  	"github.com/stretchr/testify/require"
    38  )
    39  
    40  var thresholdTests = []struct {
    41  	query string
    42  	ex    string
    43  }{
    44  	{
    45  		"foo",
    46  		`{
    47  			"query": {
    48  				"name":"fetch"
    49  			}
    50  		}`,
    51  	},
    52  	{
    53  		"sum(a)-3",
    54  		`{
    55  			"query": {
    56  				"name": "-",
    57  				"children": [
    58  					{
    59  						"name": "sum",
    60  						"children": [
    61  							{
    62  								"name": "fetch"
    63  							}
    64  						]
    65  					},
    66  					{
    67  						"name": "scalar"
    68  					}
    69  				]
    70  			}
    71  		}`,
    72  	},
    73  	{
    74  		"1 > bool 2",
    75  		`{
    76  			"query": {
    77  				"children": [
    78  					{
    79  						"name": "scalar"
    80  					},
    81  					{
    82  						"name": "scalar"
    83  					}
    84  				],
    85  				"name": ">"
    86  			}
    87  		}`,
    88  	},
    89  	{
    90  		"foo > bar",
    91  		`{
    92  			"query": {
    93  				"children": [
    94  					{
    95  						"name": "fetch"
    96  					},
    97  					{
    98  						"name": "fetch"
    99  					}
   100  				],
   101  				"name": ">"
   102  			}
   103  		}`,
   104  	},
   105  	{
   106  		"up > 13.37",
   107  		`{
   108  			"query": {
   109  				"name": "fetch"
   110  			},
   111  			"threshold": {
   112  				"comparator": ">",
   113  				"value": 13.37
   114  			}
   115  		}`,
   116  	},
   117  	{
   118  		"1 <= bool (foo or sum(rate(bar[5m])))",
   119  		`{
   120  			"query": {
   121  				"children": [
   122  					{
   123  						"name": "fetch"
   124  					},
   125  					{
   126  						"children": [
   127  							{
   128  								"children": [
   129  									{
   130  										"name": "fetch"
   131  									}
   132  								],
   133  								"name": "rate"
   134  							}
   135  						],
   136  						"name": "sum"
   137  					}
   138  				],
   139  				"name": "or"
   140  			},
   141  			"threshold": {
   142  				"comparator": ">=",
   143  				"value": 1
   144  			}
   145  		}`,
   146  	},
   147  	{
   148  		"foo == -0.31",
   149  		`{
   150  			"query": {
   151  				"name": "fetch"
   152  			},
   153  			"threshold": {
   154  				"comparator": "==",
   155  				"value": -0.31
   156  			}
   157  		}`,
   158  	},
   159  	{
   160  		"0 != bar",
   161  		`{
   162  			"query": {
   163  				"name": "fetch"
   164  			},
   165  			"threshold": {
   166  				"comparator": "!=",
   167  				"value": 0
   168  			}
   169  		}`,
   170  	},
   171  }
   172  
   173  func TestParseThreshold(t *testing.T) {
   174  	opts := executor.NewEngineOptions().
   175  		SetInstrumentOptions(instrument.NewOptions())
   176  
   177  	count := 0
   178  	parse := opts.ParseOptions().ParseFn()
   179  	opts = opts.SetParseOptions(
   180  		opts.ParseOptions().SetParseFn(
   181  			func(query string) (pql.Expr, error) {
   182  				count++
   183  				return parse(query)
   184  			},
   185  		),
   186  	)
   187  
   188  	engine := executor.NewEngine(opts)
   189  	for _, tt := range thresholdTests {
   190  		t.Run(tt.query, func(t *testing.T) {
   191  			testParseThreshold(t, engine, tt.query, tt.ex)
   192  		})
   193  	}
   194  }
   195  
   196  func testParseThreshold(t *testing.T, engine executor.Engine, query string, expected string) {
   197  	handlerOpts := options.EmptyHandlerOptions().SetEngine(engine)
   198  	h := NewPromThresholdHandler(handlerOpts)
   199  	query = fmt.Sprintf("/threshold?query=%s", url.QueryEscape(query))
   200  
   201  	req := httptest.NewRequest("GET", query, nil)
   202  	w := httptest.NewRecorder()
   203  
   204  	h.ServeHTTP(w, req)
   205  	body := w.Result().Body
   206  	defer func(body io.ReadCloser) {
   207  		require.NoError(t, body.Close())
   208  	}(body)
   209  
   210  	r, err := ioutil.ReadAll(body)
   211  	require.NoError(t, err)
   212  
   213  	ex := xtest.MustPrettyJSONString(t, expected)
   214  	actual := xtest.MustPrettyJSONString(t, string(r))
   215  	require.Equal(t, ex, actual, xtest.Diff(ex, actual))
   216  }