#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
use t::APISIX 'no_plan';

repeat_each(2);
no_long_string();
no_root_location();

add_block_preprocessor(sub {
    my ($block) = @_;

    my $init_by_lua_block = <<_EOC_;
    require "resty.core"
    apisix = require("apisix")
    core = require("apisix.core")
    apisix.http_init()

    function test(route, ctx, count)
        local balancer = require("apisix.balancer")
        local res = {}
        for i = 1, count or 12 do
            ctx.balancer_try_count = 0
            local server, err = balancer.pick_server(route, ctx)
            if err then
                ngx.say("failed: ", err)
            end

            core.log.warn("host: ", server.host, " port: ", server.port)
            res[server.host] = (res[server.host] or 0) + 1
        end

        local keys = {}
        for k,v in pairs(res) do
            table.insert(keys, k)
        end
        table.sort(keys)

        for _, key in ipairs(keys) do
            ngx.say("host: ", key, " count: ", res[key])
        end

        ctx.server_picker = nil
    end
_EOC_
    $block->set_value("init_by_lua_block", $init_by_lua_block);
});

run_tests;

__DATA__

=== TEST 1: roundrobin with same weight
--- config
    location /t {
        content_by_lua_block {
            local up_conf = {
                type = "roundrobin",
                nodes = {
                    {host = "39.97.63.215", port = 80, weight = 1, priority = 0},
                    {host = "39.97.63.216", port = 81, weight = 1, priority = 0},
                    {host = "39.97.63.217", port = 82, weight = 1, priority = 0},
                }
            }
            local ctx = {conf_version = 1}
            ctx.upstream_conf = up_conf
            ctx.upstream_version = "ver"
            ctx.upstream_key = up_conf.type .. "#route_" .. "id"

            test(route, ctx)
        }
    }
--- request
GET /t
--- response_body
host: 39.97.63.215 count: 4
host: 39.97.63.216 count: 4
host: 39.97.63.217 count: 4



=== TEST 2: roundrobin with different weight
--- config
    location /t {
        content_by_lua_block {
            local up_conf = {
                type = "roundrobin",
                nodes = {
                    {host = "39.97.63.215", port = 80, weight = 1, priority = 0},
                    {host = "39.97.63.216", port = 81, weight = 2, priority = 0},
                    {host = "39.97.63.217", port = 82, weight = 3, priority = 0},
                }
            }
            local ctx = {conf_version = 1}
            ctx.upstream_conf = up_conf
            ctx.upstream_version = "ver"
            ctx.upstream_key = up_conf.type .. "#route_" .. "id"

            test(route, ctx)
        }
    }
--- request
GET /t
--- response_body
host: 39.97.63.215 count: 2
host: 39.97.63.216 count: 4
host: 39.97.63.217 count: 6



=== TEST 3: roundrobin, cached server picker by version
--- config
    location /t {
        content_by_lua_block {
            local up_conf = {
                type = "roundrobin",
                nodes = {
                    {host = "39.97.63.215", port = 80, weight = 1, priority = 0},
                    {host = "39.97.63.216", port = 81, weight = 1, priority = 0},
                    {host = "39.97.63.217", port = 82, weight = 1, priority = 0},
                }
            }
            local ctx = {}
            ctx.upstream_conf = up_conf
            ctx.upstream_version = 1
            ctx.upstream_key = up_conf.type .. "#route_" .. "id"

            test(route, ctx)

            -- cached by version
            up_conf.nodes = {
                {host = "39.97.63.218", port = 80, weight = 1, priority = 0},
                {host = "39.97.63.219", port = 80, weight = 0, priority = 0},
            }
            test(route, ctx)

            -- update, version changed
            ctx.upstream_version = 2
            test(route, ctx)
        }
    }
--- request
GET /t
--- response_body
host: 39.97.63.215 count: 4
host: 39.97.63.216 count: 4
host: 39.97.63.217 count: 4
host: 39.97.63.215 count: 4
host: 39.97.63.216 count: 4
host: 39.97.63.217 count: 4
host: 39.97.63.218 count: 12



=== TEST 4: chash
--- config
    location /t {
        content_by_lua_block {
            local up_conf = {
                type = "chash",
                key  = "remote_addr",
                nodes = {
                    {host = "39.97.63.215", port = 80, weight = 1, priority = 0},
                    {host = "39.97.63.216", port = 81, weight = 1, priority = 0},
                    {host = "39.97.63.217", port = 82, weight = 1, priority = 0},
                }
            }
            local ctx = {
                var = {remote_addr = "127.0.0.1"},
            }
            ctx.upstream_conf = up_conf
            ctx.upstream_version = 1
            ctx.upstream_key = up_conf.type .. "#route_" .. "id"

            test(route, ctx)

            -- cached by version
            up_conf.nodes = {
                {host = "39.97.63.218", port = 80, weight = 1, priority = 0},
                {host = "39.97.63.219", port = 80, weight = 0, priority = 0},
            }
            test(route, ctx)

            -- update, version changed
            ctx.upstream_version = 2
            test(route, ctx)
        }
    }
--- request
GET /t
--- response_body
host: 39.97.63.215 count: 12
host: 39.97.63.215 count: 12
host: 39.97.63.218 count: 12



=== TEST 5: return item directly if only have one item in `nodes`
--- config
    location /t {
        content_by_lua_block {
            local up_conf = {
                type = "roundrobin",
                nodes = {
                    {host = "39.97.63.215", port = 80, weight = 1, priority = 0},
                    {host = "39.97.63.216", port = 81, weight = 1, priority = 0},
                    {host = "39.97.63.217", port = 82, weight = 1, priority = 0},
                }
            }
            local ctx = {}
            ctx.upstream_conf = up_conf
            ctx.upstream_version = 1
            ctx.upstream_key = up_conf.type .. "#route_" .. "id"

            test(route, ctx)

            -- one item in nodes, return it directly
            up_conf.nodes = {
                {host = "39.97.63.218", port = 80, weight = 1, priority = 0},
            }
            test(route, ctx)
        }
    }
--- request
GET /t
--- response_body
host: 39.97.63.215 count: 4
host: 39.97.63.216 count: 4
host: 39.97.63.217 count: 4
host: 39.97.63.218 count: 12
