github.com/rohankumardubey/aresdb@v0.0.2-0.20190517170215-e54e3ca06b9c/api/schema_handler_test.go (about) 1 // Copyright (c) 2017-2018 Uber Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package api 16 17 import ( 18 "bytes" 19 "encoding/json" 20 "errors" 21 "fmt" 22 "io/ioutil" 23 "net/http" 24 "net/http/httptest" 25 26 "github.com/uber/aresdb/memstore" 27 memMocks "github.com/uber/aresdb/memstore/mocks" 28 metaCom "github.com/uber/aresdb/metastore/common" 29 "github.com/uber/aresdb/metastore/mocks" 30 31 "github.com/gorilla/mux" 32 "github.com/onsi/ginkgo" 33 . "github.com/onsi/gomega" 34 "github.com/stretchr/testify/mock" 35 "github.com/uber/aresdb/metastore" 36 "github.com/uber/aresdb/utils" 37 ) 38 39 var _ = ginkgo.Describe("SchemaHandler", func() { 40 41 var testServer *httptest.Server 42 var hostPort string 43 var testTable = metaCom.Table{ 44 Name: "testTable", 45 Columns: []metaCom.Column{ 46 { 47 Name: "col1", 48 Type: "Int32", 49 }, 50 }, 51 PrimaryKeyColumns: []int{0}, 52 } 53 var testTableSchema = memstore.TableSchema{ 54 EnumDicts: map[string]memstore.EnumDict{ 55 "testColumn": { 56 ReverseDict: []string{"a", "b", "c"}, 57 Dict: map[string]int{ 58 "a": 0, 59 "b": 1, 60 "c": 2, 61 }, 62 }, 63 }, 64 Schema: testTable, 65 } 66 67 testMetaStore := &mocks.MetaStore{} 68 var testMemStore *memMocks.MemStore 69 var schemaHandler *SchemaHandler 70 71 ginkgo.BeforeEach(func() { 72 testMemStore = CreateMemStore(&testTableSchema, 0, nil, nil) 73 schemaHandler = NewSchemaHandler(testMetaStore) 74 testRouter := mux.NewRouter() 75 schemaHandler.Register(testRouter.PathPrefix("/schema").Subrouter()) 76 testServer = httptest.NewUnstartedServer(WithPanicHandling(testRouter)) 77 testServer.Start() 78 hostPort = testServer.Listener.Addr().String() 79 }) 80 81 ginkgo.AfterEach(func() { 82 testServer.Close() 83 }) 84 85 ginkgo.It("ListTables should work", func() { 86 testMemStore.On("GetSchemas").Return(map[string]*memstore.TableSchema{"testTable": nil}) 87 testMetaStore.On("ListTables").Return([]string{"testTable"}, nil) 88 hostPort := testServer.Listener.Addr().String() 89 resp, err := http.Get(fmt.Sprintf("http://%s/schema/tables", hostPort)) 90 Ω(err).Should(BeNil()) 91 respBody, err := ioutil.ReadAll(resp.Body) 92 Ω(err).Should(BeNil()) 93 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 94 Ω(respBody).Should(Equal([]byte(`["testTable"]`))) 95 }) 96 97 ginkgo.It("GetTable should work", func() { 98 testMetaStore.On("GetTable", "testTable").Return(&testTable, nil) 99 testMetaStore.On("GetTable", "unknown").Return(nil, metastore.ErrTableDoesNotExist) 100 resp, err := http.Get(fmt.Sprintf("http://%s/schema/tables/%s", hostPort, "testTable")) 101 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 102 Ω(err).Should(BeNil()) 103 respBody, err := ioutil.ReadAll(resp.Body) 104 Ω(err).Should(BeNil()) 105 respTable := metaCom.Table{} 106 json.Unmarshal(respBody, &respTable) 107 Ω(respTable).Should(Equal(testTableSchema.Schema)) 108 109 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 110 111 resp, err = http.Get(fmt.Sprintf("http://%s/schema/tables/%s", hostPort, "unknown")) 112 Ω(err).Should(BeNil()) 113 Ω(resp.StatusCode).Should(Equal(http.StatusNotFound)) 114 }) 115 116 ginkgo.It("AddTable should work", func() { 117 118 tableSchemaBytes, _ := json.Marshal(testTableSchema.Schema) 119 120 testMetaStore.On("CreateTable", mock.Anything).Return(nil).Once() 121 resp, _ := http.Post(fmt.Sprintf("http://%s/schema/tables", hostPort), "application/json", bytes.NewBuffer(tableSchemaBytes)) 122 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 123 124 var createdTableSchema *metaCom.Table 125 testMetaStore.On("CreateTable", mock.Anything).Run(func(args mock.Arguments) { 126 createdTableSchema = args.Get(0).(*metaCom.Table) 127 }).Return(nil).Once() 128 resp, _ = http.Post(fmt.Sprintf("http://%s/schema/tables", hostPort), "application/json", bytes.NewBuffer(tableSchemaBytes)) 129 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 130 Ω(createdTableSchema).ShouldNot(BeNil()) 131 Ω(createdTableSchema.Config).Should(Equal(metastore.DefaultTableConfig)) 132 133 testMetaStore.On("CreateTable", mock.Anything).Return(errors.New("Failed to create table")).Once() 134 resp, _ = http.Post(fmt.Sprintf("http://%s/schema/tables", hostPort), "application/json", bytes.NewBuffer(tableSchemaBytes)) 135 Ω(resp.StatusCode).Should(Equal(http.StatusInternalServerError)) 136 137 tableSchemaBytes = []byte(`{"name": ""`) 138 resp, _ = http.Post(fmt.Sprintf("http://%s/schema/tables", hostPort), "application/json", bytes.NewBuffer(tableSchemaBytes)) 139 Ω(resp.StatusCode).Should(Equal(http.StatusBadRequest)) 140 }) 141 142 ginkgo.It("UpdateTableConfig should work", func() { 143 tableSchemaBytes, _ := json.Marshal(testTableSchema.Schema) 144 145 testMetaStore.On("CreateTable", mock.Anything, mock.Anything).Return(nil).Once() 146 resp, _ := http.Post(fmt.Sprintf("http://%s/schema/tables", hostPort), "application/json", bytes.NewBuffer(tableSchemaBytes)) 147 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 148 149 testMetaStore.On("UpdateTableConfig", mock.Anything, mock.Anything).Return(nil).Once() 150 req, _ := http.NewRequest(http.MethodPut, fmt.Sprintf("http://%s/schema/tables/%s", hostPort, testTableSchema.Schema.Name), bytes.NewBuffer(tableSchemaBytes)) 151 resp, _ = http.DefaultClient.Do(req) 152 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 153 154 testMetaStore.On("UpdateTableConfig", mock.Anything, mock.Anything).Return(errors.New("Failed to create table")).Once() 155 req, _ = http.NewRequest(http.MethodPut, fmt.Sprintf("http://%s/schema/tables/%s", hostPort, testTableSchema.Schema.Name), bytes.NewBuffer(tableSchemaBytes)) 156 resp, _ = http.DefaultClient.Do(req) 157 Ω(resp.StatusCode).Should(Equal(http.StatusInternalServerError)) 158 159 tableSchemaBytes = []byte(`{"name": ""`) 160 req, _ = http.NewRequest(http.MethodPut, fmt.Sprintf("http://%s/schema/tables/%s", hostPort, testTableSchema.Schema.Name), bytes.NewBuffer(tableSchemaBytes)) 161 resp, _ = http.DefaultClient.Do(req) 162 Ω(resp.StatusCode).Should(Equal(http.StatusBadRequest)) 163 }) 164 165 ginkgo.It("DeleteTable should work", func() { 166 testMetaStore.On("DeleteTable", mock.Anything).Return(nil).Once() 167 req, _ := http.NewRequest(http.MethodDelete, fmt.Sprintf("http://%s/schema/tables/%s", hostPort, "testTable"), &bytes.Buffer{}) 168 resp, _ := http.DefaultClient.Do(req) 169 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 170 171 testMetaStore.On("DeleteTable", mock.Anything).Return(errors.New("Failed to delete table")).Once() 172 req, _ = http.NewRequest(http.MethodDelete, fmt.Sprintf("http://%s/schema/tables/%s", hostPort, "testTable"), &bytes.Buffer{}) 173 resp, _ = http.DefaultClient.Do(req) 174 Ω(resp.StatusCode).Should(Equal(http.StatusInternalServerError)) 175 bs, err := ioutil.ReadAll(resp.Body) 176 Ω(err).Should(BeNil()) 177 defer resp.Body.Close() 178 179 var errResp utils.APIError 180 err = json.Unmarshal(bs, &errResp) 181 Ω(err).Should(BeNil()) 182 Ω(errResp.Message).Should(Equal("Failed to delete table")) 183 }) 184 185 ginkgo.It("AddColumn should work", func() { 186 columnBytes := []byte(`{"name": "testCol", "type":"Int32", "defaultValue": "1"}`) 187 testMetaStore.On("AddColumn", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() 188 resp, _ := http.Post(fmt.Sprintf("http://%s/schema/tables/%s/columns", hostPort, "testTable"), "application/json", bytes.NewBuffer(columnBytes)) 189 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 190 191 columnBytes = []byte(`{"name": "testCol", "type":"Int32"}`) 192 testMetaStore.On("AddColumn", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() 193 resp, _ = http.Post(fmt.Sprintf("http://%s/schema/tables/%s/columns", hostPort, "testTable"), "application/json", bytes.NewBuffer(columnBytes)) 194 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 195 196 errorColumnBytes := []byte(`{"name": "testCol"`) 197 resp, _ = http.Post(fmt.Sprintf("http://%s/schema/tables/%s/columns", hostPort, "testTable"), "application/json", bytes.NewBuffer(errorColumnBytes)) 198 Ω(resp.StatusCode).Should(Equal(http.StatusBadRequest)) 199 200 testMetaStore.On("AddColumn", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("Failed to add columns")).Once() 201 resp, _ = http.Post(fmt.Sprintf("http://%s/schema/tables/%s/columns", hostPort, "testTable"), "application/json", bytes.NewBuffer(columnBytes)) 202 Ω(resp.StatusCode).Should(Equal(http.StatusInternalServerError)) 203 }) 204 205 ginkgo.It("DeleteColumn should work", func() { 206 testMetaStore.On("DeleteColumn", mock.Anything, mock.Anything).Return(nil).Once() 207 req, _ := http.NewRequest(http.MethodDelete, fmt.Sprintf("http://%s/schema/tables/%s/columns/%s", hostPort, "testTable", "testColumn"), &bytes.Buffer{}) 208 resp, _ := http.DefaultClient.Do(req) 209 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 210 211 testMetaStore.On("DeleteColumn", mock.Anything, mock.Anything).Return(errors.New("Failed to delete columns")).Once() 212 req, _ = http.NewRequest(http.MethodDelete, fmt.Sprintf("http://%s/schema/tables/%s/columns/%s", hostPort, "testTable", "testColumn"), &bytes.Buffer{}) 213 resp, _ = http.DefaultClient.Do(req) 214 Ω(resp.StatusCode).Should(Equal(http.StatusInternalServerError)) 215 }) 216 217 ginkgo.It("UpdateColumn should work", func() { 218 testColumnConfig1 := metaCom.ColumnConfig{ 219 PreloadingDays: 2, 220 Priority: 3, 221 } 222 223 b, err := json.Marshal(testColumnConfig1) 224 Ω(err).Should(BeNil()) 225 226 testMetaStore.On("UpdateColumn", mock.Anything, mock.Anything, mock.Anything). 227 Return(nil).Once() 228 req, _ := http.NewRequest( 229 http.MethodPut, fmt.Sprintf("http://%s/schema/tables/%s/columns/%s", 230 hostPort, "testTable", "testColumn"), bytes.NewReader(b)) 231 resp, _ := http.DefaultClient.Do(req) 232 Ω(resp.StatusCode).Should(Equal(http.StatusOK)) 233 234 testMetaStore.On("UpdateColumn", mock.Anything, mock.Anything). 235 Return(errors.New("failed to update columns")).Once() 236 req, _ = http.NewRequest(http.MethodPut, fmt.Sprintf("http://%s/schema/tables/%s/columns/%s", 237 hostPort, "testTable", "testColumn"), bytes.NewReader(b)) 238 resp, _ = http.DefaultClient.Do(req) 239 Ω(resp.StatusCode).Should(Equal(http.StatusInternalServerError)) 240 }) 241 })