imjoey commented on a change in pull request #1315: URL: https://github.com/apache/apisix-dashboard/pull/1315#discussion_r570736116
########## File path: api/internal/handler/route/route_test.go ########## @@ -14,1743 +14,1421 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package route import ( "encoding/json" + "errors" + "fmt" "net/http" "testing" - "time" "github.com/shiningrush/droplet" "github.com/shiningrush/droplet/data" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" - "github.com/apisix/manager-api/internal/conf" "github.com/apisix/manager-api/internal/core/entity" - "github.com/apisix/manager-api/internal/core/storage" "github.com/apisix/manager-api/internal/core/store" + "github.com/apisix/manager-api/internal/handler" + "github.com/apisix/manager-api/internal/utils/consts" ) -func TestRoute(t *testing.T) { - // init - err := storage.InitETCDClient(conf.ETCDConfig) - assert.Nil(t, err) - err = store.InitStores() - assert.Nil(t, err) +type testCase struct { + caseDesc string + giveInput interface{} + mockInput interface{} + mockRet interface{} + mockErr interface{} + wantRet interface{} + wantErr interface{} + called bool + serviceInput string + scriptRet interface{} + scriptErr error + serviceRet interface{} + serviceErr error + upstreamRet interface{} + upstreamErr error +} - handler := &Handler{ - routeStore: store.GetStore(store.HubKeyRoute), - svcStore: store.GetStore(store.HubKeyService), - upstreamStore: store.GetStore(store.HubKeyUpstream), - scriptStore: store.GetStore(store.HubKeyScript), +var DagScript = ` +{ + "rule":{ + "root":"451106f8-560c-43a4-acf2-2a6ed0ea57b8", + "451106f8-560c-43a4-acf2-2a6ed0ea57b8":[ + [ + "code == 403", + "b93d622c-92ef-48b4-b6bb-57e1ce893ee3" + ], + [ + "", + "988ef5c2-c896-4606-a666-3d4cbe24a731" + ] + ] + }, + "conf":{ + "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{ + "name":"uri-blocker", + "conf":{ + "block_rules":[ + "root.exe", + "root.m+" + ], + "rejected_code":403 + } + }, + "988ef5c2-c896-4606-a666-3d4cbe24a731":{ + "name":"kafka-logger", + "conf":{ + "batch_max_size":1000, + "broker_list":{ + + }, + "buffer_duration":60, + "inactive_timeout":5, + "include_req_body":false, + "kafka_topic":"1", + "key":"2", + "max_retry_count":0, + "name":"kafka logger", + "retry_delay":1, + "timeout":3 + } + }, + "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{ + "name":"fault-injection", + "conf":{ + "abort":{ + "body":"200", + "http_status":300 + }, + "delay":{ + "duration":500 + } + } + } + }, + "chart":{ + "hovered":{ + + }, + "links":{ + "3a110c30-d6f3-40b1-a8ac-b828cfaa2489":{ + "from":{ + "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", + "portId":"port3" + }, + "id":"3a110c30-d6f3-40b1-a8ac-b828cfaa2489", + "to":{ + "nodeId":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3", + "portId":"port1" + } + }, + "c1958993-c1ef-44b1-bb32-7fc6f34870c2":{ + "from":{ + "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", + "portId":"port2" + }, + "id":"c1958993-c1ef-44b1-bb32-7fc6f34870c2", + "to":{ + "nodeId":"988ef5c2-c896-4606-a666-3d4cbe24a731", + "portId":"port1" + } + }, + "f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23":{ + "from":{ + "nodeId":"451106f8-560c-43a4-acf2-2a6ed0ea57b8", + "portId":"port2" + }, + "id":"f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23", + "to":{ + "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", + "portId":"port1" + } + } + }, + "nodes":{ + "3365eca3-4bc8-4769-bab3-1485dfd6a43c":{ + "id":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", + "orientation":0, + "ports":{ + "port1":{ + "id":"port1", + "position":{ + "x":107, + "y":0 + }, + "type":"input" + }, + "port2":{ + "id":"port2", + "position":{ + "x":92, + "y":96 + }, + "properties":{ + "value":"no" + }, + "type":"output" + }, + "port3":{ + "id":"port3", + "position":{ + "x":122, + "y":96 + }, + "properties":{ + "value":"yes" + }, + "type":"output" + } + }, + "position":{ + "x":750.2627969928922, + "y":301.0370335799397 + }, + "properties":{ + "customData":{ + "name":"code == 403", + "type":1 + } + }, + "size":{ + "height":96, + "width":214 + }, + "type":"判断条件" + }, + "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{ + "id":"451106f8-560c-43a4-acf2-2a6ed0ea57b8", + "orientation":0, + "ports":{ + "port1":{ + "id":"port1", + "position":{ + "x":100, + "y":0 + }, + "properties":{ + "custom":"property" + }, + "type":"input" + }, + "port2":{ + "id":"port2", + "position":{ + "x":100, + "y":96 + }, + "properties":{ + "custom":"property" + }, + "type":"output" + } + }, + "position":{ + "x":741.5684544145346, + "y":126.75879247285502 + }, + "properties":{ + "customData":{ + "data":{ + "block_rules":[ + "root.exe", + "root.m+" + ], + "rejected_code":403 + }, + "name":"uri-blocker", + "type":0 + } + }, + "size":{ + "height":96, + "width":201 + }, + "type":"uri-blocker" + }, + "988ef5c2-c896-4606-a666-3d4cbe24a731":{ + "id":"988ef5c2-c896-4606-a666-3d4cbe24a731", + "orientation":0, + "ports":{ + "port1":{ + "id":"port1", + "position":{ + "x":106, + "y":0 + }, + "properties":{ + "custom":"property" + }, + "type":"input" + }, + "port2":{ + "id":"port2", + "position":{ + "x":106, + "y":96 + }, + "properties":{ + "custom":"property" + }, + "type":"output" + } + }, + "position":{ + "x":607.9687500000001, + "y":471.17788461538447 + }, + "properties":{ + "customData":{ + "data":{ + "batch_max_size":1000, + "broker_list":{ + + }, + "buffer_duration":60, + "inactive_timeout":5, + "include_req_body":false, + "kafka_topic":"1", + "key":"2", + "max_retry_count":0, + "name":"kafka logger", + "retry_delay":1, + "timeout":3 + }, + "name":"kafka-logger", + "type":0 + } + }, + "size":{ + "height":96, + "width":212 + }, + "type":"kafka-logger" + }, + "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{ + "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3", + "orientation":0, + "ports":{ + "port1":{ + "id":"port1", + "position":{ + "x":110, + "y":0 + }, + "properties":{ + "custom":"property" + }, + "type":"input" + }, + "port2":{ + "id":"port2", + "position":{ + "x":110, + "y":96 + }, + "properties":{ + "custom":"property" + }, + "type":"output" + } + }, + "position":{ + "x":988.9074986362261, + "y":478.62041800736495 + }, + "properties":{ + "customData":{ + "data":{ + "abort":{ + "body":"200", + "http_status":300 + }, + "delay":{ + "duration":500 + } + }, + "name":"fault-injection", + "type":0 + } + }, + "size":{ + "height":96, + "width":219 + }, + "type":"fault-injection" + } + }, + "offset":{ + "x":-376.83, + "y":87.98 + }, + "scale":0.832, + "selected":{ + "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3", + "type":"node" + } + } +}` + +func TestRoute_Get(t *testing.T) { + tests := []testCase{ + { + caseDesc: "route: get success", + giveInput: &GetInput{ID: "r1"}, + mockInput: "r1", + mockRet: &entity.Route{ + BaseInfo: entity.BaseInfo{ + ID: "r1", + }, + URI: "/test", + }, + mockErr: nil, + wantRet: &entity.Route{ + BaseInfo: entity.BaseInfo{ + ID: "r1", + }, + Script: "script", + URI: "/test", + }, + wantErr: nil, + called: true, + scriptRet: &entity.Script{ID: "r1", Script: "script"}, + scriptErr: nil, + }, + { + caseDesc: "route: store get failed", + giveInput: &GetInput{ID: "failed_key"}, + mockInput: "failed_key", + mockRet: nil, + mockErr: fmt.Errorf("get failed"), + wantRet: &data.SpecCodeResponse{ + StatusCode: http.StatusNotFound, + }, + wantErr: fmt.Errorf("get failed"), + called: true, + }, + { + caseDesc: "script: store get failed", + giveInput: &GetInput{ID: "failed_key"}, + mockInput: "failed_key", + mockRet: nil, + mockErr: fmt.Errorf("get failed"), + wantRet: &data.SpecCodeResponse{ + StatusCode: http.StatusNotFound, + }, + wantErr: fmt.Errorf("get failed"), + scriptErr: errors.New("get failed"), + called: true, + }, } - assert.NotNil(t, handler) - - //create Note: depends on lib `dag-to-lua` if script exists - ctx := droplet.NewContext() - route := &entity.Route{} - reqBody := `{ - "id": "1", - "name": "aaaa", - "uri": "/index.html", - "hosts": ["foo.com", "*.bar.com"], - "vars": [], - "remote_addrs": ["127.0.0.0/8"], - "methods": ["PUT", "GET"], - "status": 1, - "upstream": { - "type": "roundrobin", - "nodes": [{ - "host": "www.a.com", - "port": 80, - "weight": 1 - }] - }, - "script":{ - "rule":{ - "root":"451106f8-560c-43a4-acf2-2a6ed0ea57b8", - "451106f8-560c-43a4-acf2-2a6ed0ea57b8":[ - [ - "code == 403", - "b93d622c-92ef-48b4-b6bb-57e1ce893ee3" - ], - [ - "", - "988ef5c2-c896-4606-a666-3d4cbe24a731" - ] - ] - }, - "conf":{ - "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{ - "name":"uri-blocker", - "conf":{ - "block_rules":[ - "root.exe", - "root.m+" - ], - "rejected_code":403 - } - }, - "988ef5c2-c896-4606-a666-3d4cbe24a731":{ - "name":"kafka-logger", - "conf":{ - "batch_max_size":1000, - "broker_list":{ - - }, - "buffer_duration":60, - "inactive_timeout":5, - "include_req_body":false, - "kafka_topic":"1", - "key":"2", - "max_retry_count":0, - "name":"kafka logger", - "retry_delay":1, - "timeout":3 - } - }, - "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{ - "name":"fault-injection", - "conf":{ - "abort":{ - "body":"200", - "http_status":300 - }, - "delay":{ - "duration":500 - } - } - } - }, - "chart":{ - "hovered":{ - - }, - "links":{ - "3a110c30-d6f3-40b1-a8ac-b828cfaa2489":{ - "from":{ - "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", - "portId":"port3" - }, - "id":"3a110c30-d6f3-40b1-a8ac-b828cfaa2489", - "to":{ - "nodeId":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3", - "portId":"port1" - } - }, - "c1958993-c1ef-44b1-bb32-7fc6f34870c2":{ - "from":{ - "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", - "portId":"port2" - }, - "id":"c1958993-c1ef-44b1-bb32-7fc6f34870c2", - "to":{ - "nodeId":"988ef5c2-c896-4606-a666-3d4cbe24a731", - "portId":"port1" - } - }, - "f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23":{ - "from":{ - "nodeId":"451106f8-560c-43a4-acf2-2a6ed0ea57b8", - "portId":"port2" - }, - "id":"f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23", - "to":{ - "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", - "portId":"port1" - } - } - }, - "nodes":{ - "3365eca3-4bc8-4769-bab3-1485dfd6a43c":{ - "id":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", - "orientation":0, - "ports":{ - "port1":{ - "id":"port1", - "position":{ - "x":107, - "y":0 - }, - "type":"input" - }, - "port2":{ - "id":"port2", - "position":{ - "x":92, - "y":96 - }, - "properties":{ - "value":"no" - }, - "type":"output" - }, - "port3":{ - "id":"port3", - "position":{ - "x":122, - "y":96 - }, - "properties":{ - "value":"yes" - }, - "type":"output" - } - }, - "position":{ - "x":750.2627969928922, - "y":301.0370335799397 - }, - "properties":{ - "customData":{ - "name":"code == 403", - "type":1 - } - }, - "size":{ - "height":96, - "width":214 - }, - "type":"判断条件" - }, - "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{ - "id":"451106f8-560c-43a4-acf2-2a6ed0ea57b8", - "orientation":0, - "ports":{ - "port1":{ - "id":"port1", - "position":{ - "x":100, - "y":0 - }, - "properties":{ - "custom":"property" - }, - "type":"input" - }, - "port2":{ - "id":"port2", - "position":{ - "x":100, - "y":96 - }, - "properties":{ - "custom":"property" - }, - "type":"output" - } - }, - "position":{ - "x":741.5684544145346, - "y":126.75879247285502 - }, - "properties":{ - "customData":{ - "data":{ - "block_rules":[ - "root.exe", - "root.m+" - ], - "rejected_code":403 - }, - "name":"uri-blocker", - "type":0 - } - }, - "size":{ - "height":96, - "width":201 - }, - "type":"uri-blocker" - }, - "988ef5c2-c896-4606-a666-3d4cbe24a731":{ - "id":"988ef5c2-c896-4606-a666-3d4cbe24a731", - "orientation":0, - "ports":{ - "port1":{ - "id":"port1", - "position":{ - "x":106, - "y":0 - }, - "properties":{ - "custom":"property" - }, - "type":"input" - }, - "port2":{ - "id":"port2", - "position":{ - "x":106, - "y":96 - }, - "properties":{ - "custom":"property" - }, - "type":"output" - } - }, - "position":{ - "x":607.9687500000001, - "y":471.17788461538447 - }, - "properties":{ - "customData":{ - "data":{ - "batch_max_size":1000, - "broker_list":{ - - }, - "buffer_duration":60, - "inactive_timeout":5, - "include_req_body":false, - "kafka_topic":"1", - "key":"2", - "max_retry_count":0, - "name":"kafka logger", - "retry_delay":1, - "timeout":3 - }, - "name":"kafka-logger", - "type":0 - } - }, - "size":{ - "height":96, - "width":212 - }, - "type":"kafka-logger" - }, - "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{ - "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3", - "orientation":0, - "ports":{ - "port1":{ - "id":"port1", - "position":{ - "x":110, - "y":0 - }, - "properties":{ - "custom":"property" - }, - "type":"input" - }, - "port2":{ - "id":"port2", - "position":{ - "x":110, - "y":96 - }, - "properties":{ - "custom":"property" - }, - "type":"output" - } - }, - "position":{ - "x":988.9074986362261, - "y":478.62041800736495 - }, - "properties":{ - "customData":{ - "data":{ - "abort":{ - "body":"200", - "http_status":300 - }, - "delay":{ - "duration":500 - } - }, - "name":"fault-injection", - "type":0 - } - }, - "size":{ - "height":96, - "width":219 - }, - "type":"fault-injection" - } - }, - "offset":{ - "x":-376.83, - "y":87.98 - }, - "scale":0.832, - "selected":{ - "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3", - "type":"node" - } - } - } - }` - err = json.Unmarshal([]byte(reqBody), route) - assert.Nil(t, err) - ctx.SetInput(route) - ret, err := handler.Create(ctx) - assert.Nil(t, err) - // check the returned valued - objRet, ok := ret.(*entity.Route) - assert.True(t, ok) - assert.Equal(t, "1", objRet.ID) - - //sleep - time.Sleep(time.Duration(100) * time.Millisecond) - - //get - input := &GetInput{} - input.ID = "1" - ctx.SetInput(input) - ret, err = handler.Get(ctx) - stored := ret.(*entity.Route) - assert.Nil(t, err) - assert.Equal(t, stored.ID, route.ID) - - //update - route2 := &UpdateInput{} - route2.ID = "1" - reqBody = `{ - "id": "1", - "name": "aaaa", - "uri": "/index.html", - "hosts": ["foo.com", "*.bar.com"], - "remote_addrs": ["127.0.0.0/8"], - "methods": ["PUT", "GET"], - "status": 1, - "labels": { - "l1": "v1", - "l2": "v2" - }, - "upstream": { - "type": "roundrobin", - "nodes": [{ - "host": "www.a.com", - "port": 80, - "weight": 1 - }] - }, - "script":{ - "rule":{ - "root":"451106f8-560c-43a4-acf2-2a6ed0ea57b8", - "451106f8-560c-43a4-acf2-2a6ed0ea57b8":[ - [ - "code == 403", - "b93d622c-92ef-48b4-b6bb-57e1ce893ee3" - ], - [ - "", - "988ef5c2-c896-4606-a666-3d4cbe24a731" - ] - ] - }, - "conf":{ - "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{ - "name":"uri-blocker", - "conf":{ - "block_rules":[ - "root.exe", - "root.m+" - ], - "rejected_code":403 - } - }, - "988ef5c2-c896-4606-a666-3d4cbe24a731":{ - "name":"kafka-logger", - "conf":{ - "batch_max_size":1000, - "broker_list":{ - - }, - "buffer_duration":60, - "inactive_timeout":5, - "include_req_body":false, - "kafka_topic":"1", - "key":"2", - "max_retry_count":0, - "name":"kafka logger", - "retry_delay":1, - "timeout":3 - } - }, - "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{ - "name":"fault-injection", - "conf":{ - "abort":{ - "body":"200", - "http_status":300 - }, - "delay":{ - "duration":500 - } - } - } - }, - "chart":{ - "hovered":{ - - }, - "links":{ - "3a110c30-d6f3-40b1-a8ac-b828cfaa2489":{ - "from":{ - "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", - "portId":"port3" - }, - "id":"3a110c30-d6f3-40b1-a8ac-b828cfaa2489", - "to":{ - "nodeId":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3", - "portId":"port1" - } - }, - "c1958993-c1ef-44b1-bb32-7fc6f34870c2":{ - "from":{ - "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", - "portId":"port2" - }, - "id":"c1958993-c1ef-44b1-bb32-7fc6f34870c2", - "to":{ - "nodeId":"988ef5c2-c896-4606-a666-3d4cbe24a731", - "portId":"port1" - } - }, - "f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23":{ - "from":{ - "nodeId":"451106f8-560c-43a4-acf2-2a6ed0ea57b8", - "portId":"port2" - }, - "id":"f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23", - "to":{ - "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", - "portId":"port1" - } - } - }, - "nodes":{ - "3365eca3-4bc8-4769-bab3-1485dfd6a43c":{ - "id":"3365eca3-4bc8-4769-bab3-1485dfd6a43c", - "orientation":0, - "ports":{ - "port1":{ - "id":"port1", - "position":{ - "x":107, - "y":0 - }, - "type":"input" - }, - "port2":{ - "id":"port2", - "position":{ - "x":92, - "y":96 - }, - "properties":{ - "value":"no" - }, - "type":"output" - }, - "port3":{ - "id":"port3", - "position":{ - "x":122, - "y":96 - }, - "properties":{ - "value":"yes" - }, - "type":"output" - } - }, - "position":{ - "x":750.2627969928922, - "y":301.0370335799397 - }, - "properties":{ - "customData":{ - "name":"code == 403", - "type":1 - } - }, - "size":{ - "height":96, - "width":214 - }, - "type":"判断条件" - }, - "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{ - "id":"451106f8-560c-43a4-acf2-2a6ed0ea57b8", - "orientation":0, - "ports":{ - "port1":{ - "id":"port1", - "position":{ - "x":100, - "y":0 - }, - "properties":{ - "custom":"property" - }, - "type":"input" - }, - "port2":{ - "id":"port2", - "position":{ - "x":100, - "y":96 - }, - "properties":{ - "custom":"property" - }, - "type":"output" - } - }, - "position":{ - "x":741.5684544145346, - "y":126.75879247285502 - }, - "properties":{ - "customData":{ - "data":{ - "block_rules":[ - "root.exe", - "root.m+" - ], - "rejected_code":403 - }, - "name":"uri-blocker", - "type":0 - } - }, - "size":{ - "height":96, - "width":201 - }, - "type":"uri-blocker" - }, - "988ef5c2-c896-4606-a666-3d4cbe24a731":{ - "id":"988ef5c2-c896-4606-a666-3d4cbe24a731", - "orientation":0, - "ports":{ - "port1":{ - "id":"port1", - "position":{ - "x":106, - "y":0 - }, - "properties":{ - "custom":"property" - }, - "type":"input" - }, - "port2":{ - "id":"port2", - "position":{ - "x":106, - "y":96 - }, - "properties":{ - "custom":"property" - }, - "type":"output" - } - }, - "position":{ - "x":607.9687500000001, - "y":471.17788461538447 - }, - "properties":{ - "customData":{ - "data":{ - "batch_max_size":1000, - "broker_list":{ - - }, - "buffer_duration":60, - "inactive_timeout":5, - "include_req_body":false, - "kafka_topic":"1", - "key":"2", - "max_retry_count":0, - "name":"kafka logger", - "retry_delay":1, - "timeout":3 - }, - "name":"kafka-logger", - "type":0 - } - }, - "size":{ - "height":96, - "width":212 - }, - "type":"kafka-logger" - }, - "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{ - "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3", - "orientation":0, - "ports":{ - "port1":{ - "id":"port1", - "position":{ - "x":110, - "y":0 - }, - "properties":{ - "custom":"property" - }, - "type":"input" - }, - "port2":{ - "id":"port2", - "position":{ - "x":110, - "y":96 - }, - "properties":{ - "custom":"property" - }, - "type":"output" - } - }, - "position":{ - "x":988.9074986362261, - "y":478.62041800736495 - }, - "properties":{ - "customData":{ - "data":{ - "abort":{ - "body":"200", - "http_status":300 - }, - "delay":{ - "duration":500 - } - }, - "name":"fault-injection", - "type":0 - } - }, - "size":{ - "height":96, - "width":219 - }, - "type":"fault-injection" - } - }, - "offset":{ - "x":-376.83, - "y":87.98 - }, - "scale":0.832, - "selected":{ - "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3", - "type":"node" - } - } - } - }` - - err = json.Unmarshal([]byte(reqBody), route2) - assert.Nil(t, err) - ctx.SetInput(route2) - ret, err = handler.Update(ctx) - assert.Nil(t, err) - // check the returned value - objRet, ok = ret.(*entity.Route) - assert.True(t, ok) - assert.Equal(t, route2.ID, objRet.ID) - assert.Equal(t, route2.Labels, objRet.Labels) - - //sleep - time.Sleep(time.Duration(100) * time.Millisecond) - - // check ID discrepancy on Update - - // Fail: test the string body id value != string route id value - errRoute := &UpdateInput{} - errRoute.ID = "2" - err = json.Unmarshal([]byte(reqBody), errRoute) - assert.Nil(t, err) - ctx.SetInput(errRoute) - ret, err = handler.Update(ctx) - assert.NotNil(t, err) - assert.EqualError(t, err, "ID on path (2) doesn't match ID on body (1)") - assert.Equal(t, http.StatusBadRequest, ret.(*data.SpecCodeResponse).StatusCode) - - // Fail: tests the float body id value != string route id value - reqBodyErr := `{ - "id": 1, - "uri": "/index.html", - "upstream": { - "type": "roundrobin", - "nodes": [{ - "host": "www.a.com", - "port": 80, - "weight": 1 - }] - } - }` - errRoute = &UpdateInput{} - errRoute.ID = "2" - err = json.Unmarshal([]byte(reqBodyErr), errRoute) - assert.Nil(t, err) - ctx.SetInput(errRoute) - ret, err = handler.Update(ctx) - assert.NotNil(t, err) - assert.EqualError(t, err, "ID on path (2) doesn't match ID on body (1)") - assert.Equal(t, http.StatusBadRequest, ret.(*data.SpecCodeResponse).StatusCode) - - // Success: tests the float body id value is == string route id value - reqBodyErr = `{ - "id": 10, - "uri": "/index.html", - "upstream": { - "type": "roundrobin", - "nodes": [{ - "host": "www.a.com", - "port": 80, - "weight": 1 - }] - } - }` - errRoute = &UpdateInput{} - errRoute.ID = "10" - err = json.Unmarshal([]byte(reqBodyErr), errRoute) - assert.Nil(t, err) - ctx.SetInput(errRoute) - ret, err = handler.Update(ctx) - assert.Nil(t, err) - // Check the returned value - objRet, ok = ret.(*entity.Route) - assert.True(t, ok) - assert.Equal(t, errRoute.ID, objRet.ID) - - // Success: tests the Body ID can be nil - reqBodyErr = `{ - "uri": "/index.html", - "upstream": { - "type": "roundrobin", - "nodes": [{ - "host": "www.a.com", - "port": 80, - "weight": 1 - }] - } - }` - errRoute = &UpdateInput{} - errRoute.ID = "r1" - err = json.Unmarshal([]byte(reqBodyErr), errRoute) - assert.Nil(t, err) - ctx.SetInput(errRoute) - ret, err = handler.Update(ctx) - assert.Nil(t, err) - // Check the returned value - objRet, ok = ret.(*entity.Route) - assert.True(t, ok) - assert.Equal(t, errRoute.ID, objRet.ID) - - //sleep - time.Sleep(time.Duration(100) * time.Millisecond) - - //list - listInput := &ListInput{} - reqBody = `{"page_size": 1, "page": 1}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err := handler.List(ctx) - assert.Nil(t, err) - dataPage := retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 1) - - //list search match - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "name": "a", "uri": "index"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 1) - - //list search name not match - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "name": "not-exists", "uri": "index"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 0) - - //list search uri not match - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "name": "a", "uri": "not-exists"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 0) - - //list search label not match - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "label":"l3"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 0) - - //list search label match - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "label":"l1"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 1) - - //list search label match - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "label":"l1:v1"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 1) - - //list search and label not match - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "label":"l1:v2"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 0) - - // list search and status match - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "status": "1"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 1) - - // sleep - time.Sleep(time.Duration(100) * time.Millisecond) - - // list search and status not match - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "name": "a", "status": "0"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 0) - - //list search with name and status - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "name": "a", "status": "1"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 1) - - //list search with name and label - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "name": "a", "label":"l1:v1"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 1) - - //list search with uri and label - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "uri": "index", "label":"l1:v1"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 1) - - //list search with uri,name and label - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "name": "a", "uri": "index", "label":"l1:v1"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 1) - - //list search with uri,name, status and label - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "name": "a", "status": "1", "uri": "index", "label":"l1:v1"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 1) - //create route using uris - route3 := &entity.Route{} - reqBody = `{ - "id": "2", - "name": "bbbbb", - "uris": ["/aa", "/bb"], - "hosts": ["foo.com", "*.bar.com"], - "remote_addrs": ["127.0.0.0/8"], - "methods": ["PUT", "GET"], - "upstream": { - "type": "roundrobin", - "nodes": {"www.a.com:80": 1} - } - }` - err = json.Unmarshal([]byte(reqBody), route3) - assert.Nil(t, err) - ctx.SetInput(route3) - ret, err = handler.Create(ctx) - assert.Nil(t, err) - objRet, ok = ret.(*entity.Route) - assert.True(t, ok) - assert.Equal(t, "2", objRet.ID) + for _, tc := range tests { + getCalled := false + mStore := &store.MockInterface{} + + mStore.On("Get", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + getCalled = true + assert.Equal(t, tc.mockInput, args.Get(0)) + }).Return(tc.mockRet, tc.mockErr) + + sStore := &store.MockInterface{} + sStore.On("Get", mock.Anything, mock.Anything).Return(tc.scriptRet, tc.scriptErr) + + h := Handler{routeStore: mStore, scriptStore: sStore} + ctx := droplet.NewContext() + ctx.SetInput(tc.giveInput) + ret, err := h.Get(ctx) + assert.True(t, tc.called, getCalled) + assert.Equal(t, tc.wantRet, ret) + assert.Equal(t, tc.wantErr, err) + } +} - //sleep - time.Sleep(time.Duration(100) * time.Millisecond) +func TestRoute_List(t *testing.T) { + mockData := []*entity.Route{ + { + BaseInfo: entity.BaseInfo{CreateTime: 1609742634}, + Name: "r1", + URI: "/test_r1", + Labels: map[string]string{ + "version": "v1", + "build": "16", + }, + Upstream: &entity.UpstreamDef{ + Nodes: []interface{}{ + map[string]interface{}{ + "host": "39.97.63.215", + "port": float64(80), + "weight": float64(1), + }, + }, + }, + }, + { + BaseInfo: entity.BaseInfo{CreateTime: 1609742635}, + Name: "r2", + URI: "/test_r2", + Labels: map[string]string{ + "version": "v1", + "build": "16", + }, + }, + { + BaseInfo: entity.BaseInfo{CreateTime: 1609742636}, + Name: "route_test", + URI: "/test_route_test", + Labels: map[string]string{ + "version": "v2", + "build": "17", + }, + }, + { + BaseInfo: entity.BaseInfo{CreateTime: 1609742636}, + Name: "test_route", + URI: "/test_test_route", + Labels: map[string]string{ + "version": "v2", + "build": "17", + "extra": "test", + }, + }, + } - //list search match uris - listInput = &ListInput{} - reqBody = `{"page_size": 1, "page": 1, "name": "bbb", "uri": "bb"}` - err = json.Unmarshal([]byte(reqBody), listInput) - assert.Nil(t, err) - ctx.SetInput(listInput) - retPage, err = handler.List(ctx) - assert.Nil(t, err) - dataPage = retPage.(*store.ListOutput) - assert.Equal(t, len(dataPage.Rows), 1) + tests := []testCase{ + { + caseDesc: "list all route", + giveInput: &ListInput{ + Pagination: store.Pagination{ + PageSize: 10, + PageNumber: 10, + }, + }, + mockInput: store.ListInput{ + PageSize: 10, + PageNumber: 10, + }, + wantRet: &store.ListOutput{ + Rows: []interface{}{ + mockData[0], + mockData[1], + mockData[2], + mockData[3], + }, + TotalSize: 4, + }, + scriptRet: &entity.Script{ID: "r1", Script: "script"}, + called: true, + }, + { + caseDesc: "list routes with name", + giveInput: &ListInput{ + Name: "route", + Pagination: store.Pagination{ + PageSize: 10, + PageNumber: 10, + }, + }, + mockInput: store.ListInput{ + PageSize: 10, + PageNumber: 10, + }, + wantRet: &store.ListOutput{ + Rows: []interface{}{ + mockData[2], + mockData[3], + }, + TotalSize: 2, + }, + scriptRet: &entity.Script{ID: "r1", Script: "script"}, + called: true, + }, + { + caseDesc: "list routes with uri", + giveInput: &ListInput{ + URI: "test_r2", + Pagination: store.Pagination{ + PageSize: 10, + PageNumber: 10, + }, + }, + mockInput: store.ListInput{ + PageSize: 10, + PageNumber: 10, + }, + wantRet: &store.ListOutput{ + Rows: []interface{}{ + mockData[1], + }, + TotalSize: 1, + }, + scriptRet: &entity.Script{ID: "r1", Script: "script"}, + called: true, + }, + { + caseDesc: "list routes with label", + giveInput: &ListInput{ + Label: "version:v1", + Pagination: store.Pagination{ + PageSize: 10, + PageNumber: 10, + }, + }, + mockInput: store.ListInput{ + PageSize: 10, + PageNumber: 10, + }, + wantRet: &store.ListOutput{ + Rows: []interface{}{ + mockData[0], + mockData[1], + }, + TotalSize: 2, + }, + scriptRet: &entity.Script{ID: "s1", Script: "script"}, + called: true, + }, + { + caseDesc: "list routes with label", + giveInput: &ListInput{ + Label: "extra", + Pagination: store.Pagination{ + PageSize: 10, + PageNumber: 10, + }, + }, + mockInput: store.ListInput{ + PageSize: 10, + PageNumber: 10, + }, + wantRet: &store.ListOutput{ + Rows: []interface{}{ + mockData[3], + }, + TotalSize: 1, + }, + scriptRet: &entity.Script{ID: "s1", Script: "script"}, + called: true, + }, + { + caseDesc: "list routes and test format", + giveInput: &ListInput{ + Name: "r1", + Pagination: store.Pagination{ + PageSize: 10, + PageNumber: 10, + }, + }, + mockInput: store.ListInput{ + PageSize: 10, + PageNumber: 10, + }, + wantRet: &store.ListOutput{ + Rows: []interface{}{ + &entity.Route{ + BaseInfo: entity.BaseInfo{CreateTime: 1609742634}, + Name: "r1", + URI: "/test_r1", + Labels: map[string]string{ + "version": "v1", + "build": "16", + }, + Script: "script", + Upstream: &entity.UpstreamDef{ + Nodes: []*entity.Node{ + { + Host: "39.97.63.215", + Port: 80, + Weight: 1, + }, + }, + }, + }, + }, - //delete test data - inputDel := &BatchDelete{} - reqBody = `{"ids": "1,2"}` - err = json.Unmarshal([]byte(reqBody), inputDel) - assert.Nil(t, err) - ctx.SetInput(inputDel) - _, err = handler.BatchDelete(ctx) - assert.Nil(t, err) + TotalSize: 1, + }, + called: true, + }, + } - //sleep - time.Sleep(time.Duration(100) * time.Millisecond) + for _, tc := range tests { + t.Run(tc.caseDesc, func(t *testing.T) { + getCalled := false + mStore := &store.MockInterface{} + mStore.On("List", mock.Anything).Run(func(args mock.Arguments) { + getCalled = true + input := args.Get(0).(store.ListInput) + mockInput := tc.mockInput.(store.ListInput) + assert.Equal(t, mockInput.PageSize, input.PageSize) + assert.Equal(t, mockInput.PageNumber, input.PageNumber) + }).Return(func(input store.ListInput) *store.ListOutput { + var returnData []interface{} + for _, c := range mockData { + if input.Predicate(c) { + if input.Format == nil { + returnData = append(returnData, c) + continue + } + + returnData = append(returnData, input.Format(c)) + } + } + + return &store.ListOutput{ + Rows: returnData, + TotalSize: len(returnData), + } + }, tc.mockErr) + + sStore := &store.MockInterface{} + sStore.On("Get", mock.Anything, mock.Anything).Return(tc.scriptRet, tc.scriptErr) + + h := Handler{routeStore: mStore, scriptStore: sStore} + ctx := droplet.NewContext() + ctx.SetInput(tc.giveInput) + + ret, err := h.List(ctx) + assert.Equal(t, tc.called, getCalled) + assert.Equal(t, tc.wantRet, ret) + assert.Equal(t, tc.wantErr, err) + }) + } +} - //get route -- deleted, not found - getInput := &GetInput{} - reqBody = `{"id": "1"}` - err = json.Unmarshal([]byte(reqBody), getInput) - assert.Nil(t, err) - ctx.SetInput(getInput) - ret, err = handler.Get(ctx) - assert.EqualError(t, err, "data not found") - assert.Equal(t, http.StatusNotFound, ret.(*data.SpecCodeResponse).StatusCode) +func TestRoute_Create(t *testing.T) { + scriptMap := make(map[string]interface{}) - //delete test data - reqBody = `{"ids": "not-exists"}` - err = json.Unmarshal([]byte(reqBody), inputDel) + err := json.Unmarshal([]byte(DagScript), &scriptMap) assert.Nil(t, err) - ctx.SetInput(inputDel) - ret, err = handler.BatchDelete(ctx) - assert.NotNil(t, err) - assert.Equal(t, http.StatusNotFound, ret.(*data.SpecCodeResponse).StatusCode) - //create route with not exist upstream id - route4 := &entity.Route{} - reqBody = `{ - "id": "2222", - "name": "r222", - "uris": ["/aa", "/bb"], - "upstream_id": "not-exists" - }` - err = json.Unmarshal([]byte(reqBody), route4) + luaCode, err := generateLuaCode(scriptMap) assert.Nil(t, err) - ctx.SetInput(route4) - ret, err = handler.Create(ctx) - assert.NotNil(t, err) - assert.Equal(t, http.StatusBadRequest, ret.(*data.SpecCodeResponse).StatusCode) - //type:chash, hash_on: vars, wrong key - route5 := &entity.Route{} - reqBody = `{ - "id": "1", - "methods": ["GET"], - "upstream": { - "nodes": { - "127.0.0.1:8080": 1 - }, - "type": "chash", - "hash_on":"vars", - "key": "not_support" - }, - "desc": "new route", - "uri": "/index.html" - }` - err = json.Unmarshal([]byte(reqBody), route5) - assert.Nil(t, err) - ctx.SetInput(route5) - ret, err = handler.Create(ctx) - assert.NotNil(t, err) - assert.Equal(t, http.StatusBadRequest, ret.(*data.SpecCodeResponse).StatusCode) + tests := []testCase{ + { + caseDesc: "create route success", + giveInput: &entity.Route{ + BaseInfo: entity.BaseInfo{ + ID: "s1", + CreateTime: 1609746531, + }, + Name: "s1", + Desc: "test_route", + UpstreamID: "u1", + ServiceID: "s1", + Script: "", + Labels: map[string]string{ + "version": "v1", + }, + }, + mockInput: &entity.Route{ + BaseInfo: entity.BaseInfo{ + ID: "s1", + CreateTime: 1609746531, + }, + Name: "s1", + Desc: "test_route", + UpstreamID: "u1", + ServiceID: "s1", + ScriptID: "s1", + Script: "", + Labels: map[string]string{ + "version": "v1", + }, + }, + serviceRet: "service", + serviceErr: nil, + upstreamRet: "upstream", + upstreamErr: nil, + scriptRet: "script", + scriptErr: nil, + wantRet: nil, Review comment: +1. We shall keep the behavior of the mock object same as the real one. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org