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

     1  // Copyright (c) 2020 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 handler
    22  
    23  import (
    24  	"fmt"
    25  	"io/ioutil"
    26  	"net/http"
    27  	"net/http/httptest"
    28  	"testing"
    29  	"time"
    30  
    31  	"github.com/stretchr/testify/assert"
    32  	"github.com/stretchr/testify/require"
    33  
    34  	"github.com/m3db/m3/src/dbnode/client"
    35  	"github.com/m3db/m3/src/query/api/v1/options"
    36  	"github.com/m3db/m3/src/query/storage/m3"
    37  	"github.com/m3db/m3/src/x/ident"
    38  	xtest "github.com/m3db/m3/src/x/test"
    39  )
    40  
    41  func TestReadyHandler(t *testing.T) {
    42  	tests := []struct {
    43  		name               string
    44  		prepare            func(session *client.MockSession)
    45  		queryString        string
    46  		expectedStatusCode int
    47  		expectedResponse   string
    48  	}{
    49  		{
    50  			name: "healthy",
    51  			prepare: func(session *client.MockSession) {
    52  				session.EXPECT().ReadClusterAvailability().Return(true, nil)
    53  				session.EXPECT().WriteClusterAvailability().Return(true, nil)
    54  			},
    55  			expectedStatusCode: http.StatusOK,
    56  			expectedResponse: `{
    57  				"readyReads": [
    58  				  {
    59  					"attributes": {
    60  					  "metricsType": "unaggregated",
    61  					  "resolution": "0s",
    62  					  "retention": "24h0m0s"
    63  					},
    64  					"id": "test-ns"
    65  				  }
    66  				],
    67  				"readyWrites": [
    68  				  {
    69  					"attributes": {
    70  					  "metricsType": "unaggregated",
    71  					  "resolution": "0s",
    72  					  "retention": "24h0m0s"
    73  					},
    74  					"id": "test-ns"
    75  				  }
    76  				]
    77  			  }`,
    78  		},
    79  		{
    80  			name: "unhealthy",
    81  			prepare: func(session *client.MockSession) {
    82  				session.EXPECT().ReadClusterAvailability().Return(true, nil)
    83  				session.EXPECT().WriteClusterAvailability().Return(false, nil)
    84  			},
    85  			expectedStatusCode: http.StatusInternalServerError,
    86  			expectedResponse: `{
    87  				"readyReads": [
    88  				  {
    89  					"attributes": {
    90  					  "metricsType": "unaggregated",
    91  					  "resolution": "0s",
    92  					  "retention": "24h0m0s"
    93  					},
    94  					"id": "test-ns"
    95  				  }
    96  				],
    97  				"notReadyWrites": [
    98  				  {
    99  					"attributes": {
   100  					  "metricsType": "unaggregated",
   101  					  "resolution": "0s",
   102  					  "retention": "24h0m0s"
   103  					},
   104  					"id": "test-ns"
   105  				  }
   106  				]
   107  			  }`,
   108  		},
   109  		{
   110  			name: "healthy only reads",
   111  			prepare: func(session *client.MockSession) {
   112  				session.EXPECT().ReadClusterAvailability().Return(true, nil)
   113  				session.EXPECT().WriteClusterAvailability().Return(false, nil)
   114  			},
   115  			queryString:        "writes=false",
   116  			expectedStatusCode: http.StatusOK,
   117  			expectedResponse: `{
   118  				"readyReads": [
   119  				  {
   120  					"attributes": {
   121  					  "metricsType": "unaggregated",
   122  					  "resolution": "0s",
   123  					  "retention": "24h0m0s"
   124  					},
   125  					"id": "test-ns"
   126  				  }
   127  				],
   128  				"notReadyWrites": [
   129  				  {
   130  					"attributes": {
   131  					  "metricsType": "unaggregated",
   132  					  "resolution": "0s",
   133  					  "retention": "24h0m0s"
   134  					},
   135  					"id": "test-ns"
   136  				  }
   137  				]
   138  			  }`,
   139  		},
   140  		{
   141  			name: "healthy only writes",
   142  			prepare: func(session *client.MockSession) {
   143  				session.EXPECT().ReadClusterAvailability().Return(false, nil)
   144  				session.EXPECT().WriteClusterAvailability().Return(true, nil)
   145  			},
   146  			queryString:        "reads=false",
   147  			expectedStatusCode: http.StatusOK,
   148  			expectedResponse: `{
   149  				"notReadyReads": [
   150  				  {
   151  					"attributes": {
   152  					  "metricsType": "unaggregated",
   153  					  "resolution": "0s",
   154  					  "retention": "24h0m0s"
   155  					},
   156  					"id": "test-ns"
   157  				  }
   158  				],
   159  				"readyWrites": [
   160  				  {
   161  					"attributes": {
   162  					  "metricsType": "unaggregated",
   163  					  "resolution": "0s",
   164  					  "retention": "24h0m0s"
   165  					},
   166  					"id": "test-ns"
   167  				  }
   168  				]
   169  			  }`,
   170  		},
   171  	}
   172  
   173  	for _, test := range tests {
   174  		t.Run(test.name, func(t *testing.T) {
   175  			ctrl := xtest.NewController(t)
   176  			defer ctrl.Finish()
   177  
   178  			session := client.NewMockSession(ctrl)
   179  
   180  			test.prepare(session)
   181  
   182  			clusters, err := m3.NewClusters(m3.UnaggregatedClusterNamespaceDefinition{
   183  				NamespaceID: ident.StringID("test-ns"),
   184  				Session:     session,
   185  				Retention:   24 * time.Hour,
   186  			})
   187  			require.NoError(t, err)
   188  
   189  			opts := options.EmptyHandlerOptions().SetClusters(clusters)
   190  			readyHandler := NewReadyHandler(opts)
   191  
   192  			w := httptest.NewRecorder()
   193  			url := ReadyURL
   194  			if test.queryString != "" {
   195  				url += fmt.Sprintf("?%s", test.queryString)
   196  			}
   197  			req := httptest.NewRequest(ReadyHTTPMethod, url, nil)
   198  
   199  			readyHandler.ServeHTTP(w, req)
   200  
   201  			resp := w.Result()
   202  			defer resp.Body.Close()
   203  			body, err := ioutil.ReadAll(resp.Body)
   204  			assert.NoError(t, err)
   205  			assert.Equal(t, test.expectedStatusCode, resp.StatusCode)
   206  
   207  			expected := xtest.MustPrettyJSONString(t, test.expectedResponse)
   208  			actual := xtest.MustPrettyJSONString(t, string(body))
   209  
   210  			assert.Equal(t, expected, actual, xtest.Diff(expected, actual))
   211  		})
   212  	}
   213  }
   214  
   215  func TestReadyHandlerNoClusters(t *testing.T) {
   216  	ctrl := xtest.NewController(t)
   217  	defer ctrl.Finish()
   218  
   219  	opts := options.EmptyHandlerOptions()
   220  	readyHandler := NewReadyHandler(opts)
   221  
   222  	w := httptest.NewRecorder()
   223  	url := ReadyURL
   224  	req := httptest.NewRequest(ReadyHTTPMethod, url, nil)
   225  
   226  	readyHandler.ServeHTTP(w, req)
   227  
   228  	resp := w.Result()
   229  	defer resp.Body.Close()
   230  	body, err := ioutil.ReadAll(resp.Body)
   231  	assert.NoError(t, err)
   232  	assert.Equal(t, http.StatusOK, resp.StatusCode)
   233  
   234  	expected := "{}"
   235  	actual := xtest.MustPrettyJSONString(t, string(body))
   236  
   237  	assert.Equal(t, expected, actual, xtest.Diff(expected, actual))
   238  }