# vim:set ft= ts=4 sw=4 et fdm=marker:

use Test::Nginx::Socket::Lua::Stream;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');

#repeat_each(2);

plan tests => repeat_each() * 39;

#no_diff();
no_long_string();
#master_on();
#workers(2);

run_tests();

__DATA__

=== TEST 1: merge 2 single-page free blocks (forcibly evicted, merge forward)
--- stream_config
    lua_shared_dict dogs 20k;
--- stream_server_config
    content_by_lua_block {
        local dogs = ngx.shared.dogs

        local function check_key(key)
            local res, err = dogs:get(key)
            if res then
                ngx.say("found ", key, ": ", #res)
            else
                if not err then
                    ngx.say(key, " not found")
                else
                    ngx.say("failed to fetch key: ", err)
                end
            end
        end

        local function set_key(key, value)
            local ok, err, force = dogs:set(key, value)
            if ok then
                ngx.print("successfully set ", key)
                if force then
                    ngx.say(" with force.")
                else
                    ngx.say(".")
                end
            else
                ngx.say("failed to set ", key, ": ", err)
            end
        end

        for i = 1, 2 do
            set_key("foo", string.rep("a", 4000))
            set_key("bar", string.rep("b", 4001))
            set_key("baz", string.rep("c", 8102))

            check_key("foo")
            check_key("bar")
            check_key("baz")
        end

        collectgarbage()
    }
--- stap
global first_time = 1
global active = 1

F(ngx_stream_lua_shdict_init_zone) {
    active = 0
}

F(ngx_stream_lua_shdict_init_zone).return {
    active = 1
}

F(ngx_slab_alloc_pages) {
    if (first_time) {
        printf("total pages: %d\n", $pool->pages->slab)
        first_time = 0
    }
    if (active) {
        printf("alloc pages: %d", $pages)
        //print_ubacktrace()
    } else {
        printf("init zone alloc pages: %d", $pages)
    }
}

F(ngx_slab_alloc_pages).return {
    if ($return) {
        printf(" ok\n")

    } else {
        printf(" NOT OK\n")
    }
}

F(ngx_slab_free_pages) {
    printf("free pages: %d\n", $pages)
}

--- stap_out
total pages: 4
init zone alloc pages: 1 ok
init zone alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 ok
alloc pages: 1 NOT OK
free pages: 2
alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 ok

--- stream_response
successfully set foo.
successfully set bar.
successfully set baz with force.
foo not found
bar not found
found baz: 8102
successfully set foo with force.
successfully set bar.
successfully set baz with force.
foo not found
bar not found
found baz: 8102

--- no_error_log
[error]



=== TEST 2: merge 2 single-page free slabs (forcibly evicted, merge backward)
--- stream_config
    lua_shared_dict dogs 20k;
--- stream_server_config
    content_by_lua_block {
        local dogs = ngx.shared.dogs

        local function check_key(key)
            local res, err = dogs:get(key)
            if res then
                ngx.say("found ", key, ": ", #res)
            else
                if not err then
                    ngx.say(key, " not found")
                else
                    ngx.say("failed to fetch key: ", err)
                end
            end
        end

        local function set_key(key, value)
            local ok, err, force = dogs:set(key, value)
            if ok then
                ngx.print("successfully set ", key)
                if force then
                    ngx.say(" with force.")
                else
                    ngx.say(".")
                end
            else
                ngx.say("failed to set ", key, ": ", err)
            end
        end

        for i = 1, 2 do
            set_key("foo", string.rep("a", 4000))
            set_key("bar", string.rep("b", 4001))
            check_key("foo")
            set_key("baz", string.rep("c", 8102))

            check_key("foo")
            check_key("bar")
            check_key("baz")
        end

        collectgarbage()
    }
--- stap
global first_time = 1
global active = 1

F(ngx_stream_lua_shdict_init_zone) {
    active = 0
}

F(ngx_stream_lua_shdict_init_zone).return {
    active = 1
}

F(ngx_slab_alloc_pages) {
    if (first_time) {
        printf("total pages: %d\n", $pool->pages->slab)
        first_time = 0
    }
    if (active) {
        printf("alloc pages: %d", $pages)
        //print_ubacktrace()
    } else {
        printf("init zone alloc pages: %d", $pages)
    }
}

F(ngx_slab_alloc_pages).return {
    if ($return) {
        printf(" ok\n")

    } else {
        printf(" NOT OK\n")
    }
}

F(ngx_slab_free_pages) {
    printf("free pages: %d\n", $pages)
}

--- stap_out
total pages: 4
init zone alloc pages: 1 ok
init zone alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 ok
alloc pages: 1 NOT OK
free pages: 2
alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 ok

--- stream_response
successfully set foo.
successfully set bar.
found foo: 4000
successfully set baz with force.
foo not found
bar not found
found baz: 8102
successfully set foo with force.
successfully set bar.
found foo: 4000
successfully set baz with force.
foo not found
bar not found
found baz: 8102

--- no_error_log
[error]



=== TEST 3: merge 3 single-page free slabs (actively deleted, merge backward AND forward)
--- stream_config
    lua_shared_dict dogs 25k;
--- stream_server_config
    content_by_lua_block {
        local dogs = ngx.shared.dogs

        local function check_key(key)
            local res, err = dogs:get(key)
            if res then
                ngx.say("found ", key, ": ", #res)
            else
                if not err then
                    ngx.say(key, " not found")
                else
                    ngx.say("failed to fetch key: ", err)
                end
            end
        end

        local function set_key(key, value)
            local ok, err, force = dogs:set(key, value)
            if ok then
                ngx.print("successfully set ", key)
                if force then
                    ngx.say(" with force.")
                else
                    ngx.say(".")
                end
            else
                ngx.say("failed to set ", key, ": ", err)
            end
        end

        local function safe_set_key(key, value)
            local ok, err = dogs:safe_set(key, value)
            if ok then
                ngx.say("successfully safe set ", key)
            else
                ngx.say("failed to safe set ", key, ": ", err)
            end
        end

        for i = 1, 2 do
            set_key("foo", string.rep("a", 4000))
            set_key("bar", string.rep("b", 4001))
            set_key("baz", string.rep("c", 4002))

            check_key("foo")
            check_key("bar")
            check_key("baz")

            dogs:delete("foo")
            safe_set_key("blah", string.rep("a", 8100))
            dogs:delete("baz")
            safe_set_key("blah", string.rep("a", 8100))
            dogs:delete("bar")
            safe_set_key("blah", string.rep("a", 12010))
        end

        collectgarbage()
    }
--- stap
global first_time = 1
global active = 1

F(ngx_stream_lua_shdict_init_zone) {
    active = 0
}

F(ngx_stream_lua_shdict_init_zone).return {
    active = 1
}

F(ngx_slab_alloc_pages) {
    if (first_time) {
        printf("total pages: %d\n", $pool->pages->slab)
        first_time = 0
    }
    if (active) {
        printf("alloc pages: %d", $pages)
        //print_ubacktrace()
    } else {
        printf("init zone alloc pages: %d", $pages)
    }
}

F(ngx_slab_alloc_pages).return {
    if ($return) {
        printf(" ok\n")

    } else {
        printf(" NOT OK\n")
    }
}

F(ngx_slab_free_pages) {
    printf("free pages: %d\n", $pages)
}

--- stap_out
total pages: 5
init zone alloc pages: 1 ok
init zone alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
free pages: 1
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 3 ok
alloc pages: 1 NOT OK
free pages: 3
alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
free pages: 1
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 3 ok

--- stream_response
successfully set foo.
successfully set bar.
successfully set baz.
found foo: 4000
found bar: 4001
found baz: 4002
failed to safe set blah: no memory
failed to safe set blah: no memory
successfully safe set blah
successfully set foo with force.
successfully set bar.
successfully set baz.
found foo: 4000
found bar: 4001
found baz: 4002
failed to safe set blah: no memory
failed to safe set blah: no memory
successfully safe set blah

--- no_error_log
[error]



=== TEST 4: merge one single-page block backward, but no more
--- stream_config
    lua_shared_dict dogs 25k;
--- stream_server_config
    content_by_lua_block {
        local dogs = ngx.shared.dogs

        local function check_key(key)
            local res, err = dogs:get(key)
            if res then
                ngx.say("found ", key, ": ", #res)
            else
                if not err then
                    ngx.say(key, " not found")
                else
                    ngx.say("failed to fetch key: ", err)
                end
            end
        end

        local function set_key(key, value)
            local ok, err, force = dogs:set(key, value)
            if ok then
                ngx.print("successfully set ", key)
                if force then
                    ngx.say(" with force.")
                else
                    ngx.say(".")
                end
            else
                ngx.say("failed to set ", key, ": ", err)
            end
        end

        local function safe_set_key(key, value)
            local ok, err = dogs:safe_set(key, value)
            if ok then
                ngx.say("successfully safe set ", key)
            else
                ngx.say("failed to safe set ", key, ": ", err)
            end
        end

        for i = 1, 1 do
            set_key("foo", string.rep("a", 4000))
            set_key("bar", string.rep("b", 4001))
            set_key("baz", string.rep("c", 4002))

            check_key("foo")
            check_key("bar")
            check_key("baz")

            dogs:delete("bar")
            safe_set_key("blah", string.rep("a", 8100))
            dogs:delete("baz")
            safe_set_key("blah", string.rep("a", 8100))
            check_key("foo")
            dogs:delete("foo")
            check_key("blah")
        end

        collectgarbage()
    }
--- stap
global first_time = 1
global active = 1

F(ngx_stream_lua_shdict_init_zone) {
    active = 0
}

F(ngx_stream_lua_shdict_init_zone).return {
    active = 1
}

F(ngx_slab_alloc_pages) {
    if (first_time) {
        printf("total pages: %d\n", $pool->pages->slab)
        first_time = 0
    }
    if (active) {
        printf("alloc pages: %d", $pages)
        //print_ubacktrace()
    } else {
        printf("init zone alloc pages: %d", $pages)
    }
}

F(ngx_slab_alloc_pages).return {
    if ($return) {
        printf(" ok\n")

    } else {
        printf(" NOT OK\n")
    }
}

F(ngx_slab_free_pages) {
    printf("free pages: %d\n", $pages)
}

--- stap_out
total pages: 5
init zone alloc pages: 1 ok
init zone alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
free pages: 1
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 ok
free pages: 1

--- stream_response
successfully set foo.
successfully set bar.
successfully set baz.
found foo: 4000
found bar: 4001
found baz: 4002
failed to safe set blah: no memory
successfully safe set blah
found foo: 4000
found blah: 8100

--- no_error_log
[error]



=== TEST 5: merge one single-page block forward, but no more
--- stream_config
    lua_shared_dict dogs 25k;
--- stream_server_config
    content_by_lua_block {
        local dogs = ngx.shared.dogs

        local function check_key(key)
            local res, err = dogs:get(key)
            if res then
                ngx.say("found ", key, ": ", #res)
            else
                if not err then
                    ngx.say(key, " not found")
                else
                    ngx.say("failed to fetch key: ", err)
                end
            end
        end

        local function set_key(key, value)
            local ok, err, force = dogs:set(key, value)
            if ok then
                ngx.print("successfully set ", key)
                if force then
                    ngx.say(" with force.")
                else
                    ngx.say(".")
                end
            else
                ngx.say("failed to set ", key, ": ", err)
            end
        end

        local function safe_set_key(key, value)
            local ok, err = dogs:safe_set(key, value)
            if ok then
                ngx.say("successfully safe set ", key)
            else
                ngx.say("failed to safe set ", key, ": ", err)
            end
        end

        for i = 1, 1 do
            set_key("foo", string.rep("a", 4000))
            set_key("bar", string.rep("b", 4001))
            set_key("baz", string.rep("c", 4002))

            check_key("foo")
            check_key("bar")
            check_key("baz")

            dogs:delete("bar")
            safe_set_key("blah", string.rep("a", 8100))
            dogs:delete("foo")
            safe_set_key("blah", string.rep("a", 8100))
            check_key("baz")
            dogs:delete("baz")
            check_key("blah")
        end

        collectgarbage()
    }
--- stap
global first_time = 1
global active = 1

F(ngx_stream_lua_shdict_init_zone) {
    active = 0
}

F(ngx_stream_lua_shdict_init_zone).return {
    active = 1
}

F(ngx_slab_alloc_pages) {
    if (first_time) {
        printf("total pages: %d\n", $pool->pages->slab)
        first_time = 0
    }
    if (active) {
        printf("alloc pages: %d", $pages)
        //print_ubacktrace()
    } else {
        printf("init zone alloc pages: %d", $pages)
    }
}

F(ngx_slab_alloc_pages).return {
    if ($return) {
        printf(" ok\n")

    } else {
        printf(" NOT OK\n")
    }
}

F(ngx_slab_free_pages) {
    printf("free pages: %d\n", $pages)
}

--- stap_out
total pages: 5
init zone alloc pages: 1 ok
init zone alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
free pages: 1
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 ok
free pages: 1

--- stream_response
successfully set foo.
successfully set bar.
successfully set baz.
found foo: 4000
found bar: 4001
found baz: 4002
failed to safe set blah: no memory
successfully safe set blah
found baz: 4002
found blah: 8100

--- no_error_log
[error]



=== TEST 6: merge 2 multi-page blocks (forcibly evicted, merge backward)
--- stream_config
    lua_shared_dict dogs 30k;
--- stream_server_config
    content_by_lua_block {
        local dogs = ngx.shared.dogs

        local function check_key(key)
            local res, err = dogs:get(key)
            if res then
                ngx.say("found ", key, ": ", #res)
            else
                if not err then
                    ngx.say(key, " not found")
                else
                    ngx.say("failed to fetch key: ", err)
                end
            end
        end

        local function set_key(key, value)
            local ok, err, force = dogs:set(key, value)
            if ok then
                ngx.print("successfully set ", key)
                if force then
                    ngx.say(" with force.")
                else
                    ngx.say(".")
                end
            else
                ngx.say("failed to set ", key, ": ", err)
            end
        end

        local function safe_set_key(key, value)
            local ok, err = dogs:safe_set(key, value)
            if ok then
                ngx.say("successfully safe set ", key)
            else
                ngx.say("failed to safe set ", key, ": ", err)
            end
        end

        for i = 1, 1 do
            set_key("foo", string.rep("a", 8100))
            set_key("bar", string.rep("b", 8101))
            check_key("foo")
            safe_set_key("baz", string.rep("c", 16300))
            dogs:delete("foo")
            check_key("bar")
            dogs:delete("bar")
            safe_set_key("baz", string.rep("c", 16300))

            check_key("foo")
            check_key("bar")
            check_key("baz")
        end

        collectgarbage()
    }
--- stap
global first_time = 1
global active = 1

F(ngx_stream_lua_shdict_init_zone) {
    active = 0
}

F(ngx_stream_lua_shdict_init_zone).return {
    active = 1
}

F(ngx_slab_alloc_pages) {
    if (first_time) {
        printf("total pages: %d\n", $pool->pages->slab)
        first_time = 0
    }
    if (active) {
        printf("alloc pages: %d", $pages)
        //print_ubacktrace()
    } else {
        printf("init zone alloc pages: %d", $pages)
    }
}

F(ngx_slab_alloc_pages).return {
    if ($return) {
        printf(" ok\n")

    } else {
        printf(" NOT OK\n")
    }
}

F(ngx_slab_free_pages) {
    printf("free pages: %d\n", $pages)
}

--- stap_out
total pages: 6
init zone alloc pages: 1 ok
init zone alloc pages: 1 ok
alloc pages: 2 ok
alloc pages: 2 ok
alloc pages: 4 NOT OK
free pages: 2
free pages: 2
alloc pages: 4 ok

--- stream_response
successfully set foo.
successfully set bar.
found foo: 8100
failed to safe set baz: no memory
found bar: 8101
successfully safe set baz
foo not found
bar not found
found baz: 16300

--- no_error_log
[error]



=== TEST 7: merge big slabs (less than max slab size) backward
--- stream_config
    lua_shared_dict dogs 20k;
--- stream_server_config
    content_by_lua_block {
        local dogs = ngx.shared.dogs

        local function check_key(key)
            local res, err = dogs:get(key)
            if res then
                ngx.say("found ", key, ": ", #res)
            else
                if not err then
                    ngx.say(key, " not found")
                else
                    ngx.say("failed to fetch key: ", err)
                end
            end
        end

        local function set_key(key, value)
            local ok, err, force = dogs:set(key, value)
            if ok then
                ngx.print("successfully set ", key)
                if force then
                    ngx.say(" with force.")
                else
                    ngx.say(".")
                end
            else
                ngx.say("failed to set ", key, ": ", err)
            end
        end

        local function safe_set_key(key, value)
            local ok, err = dogs:safe_set(key, value)
            if ok then
                ngx.say("successfully safe set ", key)
            else
                ngx.say("failed to safe set ", key, ": ", err)
            end
        end

        for i = 1, 1 do
            for j = 1, 50 do
                dogs:set("foo" .. j, string.rep("a", 5))
            end
            set_key("bar", string.rep("a", 4000))

            for j = 1, 50 do
                dogs:delete("foo" .. j)
            end

            safe_set_key("baz", string.rep("b", 8100))
            check_key("bar")

            ngx.say("delete bar")
            dogs:delete("bar")

            safe_set_key("baz", string.rep("b", 8100))
        end

        collectgarbage()
    }
--- stap
global first_time = 1
global active = 1

F(ngx_stream_lua_shdict_init_zone) {
    active = 0
}

F(ngx_stream_lua_shdict_init_zone).return {
    active = 1
}

F(ngx_slab_alloc_pages) {
    if (first_time) {
        //printf("slab max size: %d\n", @var("ngx_slab_max_size"))
        printf("total pages: %d\n", $pool->pages->slab)
        first_time = 0
    }
    if (active) {
        printf("alloc pages: %d", $pages)
        //print_ubacktrace()
    } else {
        printf("init zone alloc pages: %d", $pages)
    }
}

F(ngx_slab_alloc_pages).return {
    if ($return) {
        printf(" ok\n")

    } else {
        printf(" NOT OK\n")
    }
}

F(ngx_slab_free_pages) {
    printf("free pages: %d\n", $pages)
}

--- stap_out
total pages: 4
init zone alloc pages: 1 ok
init zone alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
free pages: 1
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 ok

--- stream_response
successfully set bar.
failed to safe set baz: no memory
found bar: 4000
delete bar
successfully safe set baz

--- no_error_log
[error]



=== TEST 8: cannot merge in-used big slabs page (backward)
--- stream_config
    lua_shared_dict dogs 20k;
--- stream_server_config
    content_by_lua_block {
        local dogs = ngx.shared.dogs

        local function check_key(key)
            local res, err = dogs:get(key)
            if res then
                ngx.say("found ", key, ": ", #res)
            else
                if not err then
                    ngx.say(key, " not found")
                else
                    ngx.say("failed to fetch key: ", err)
                end
            end
        end

        local function set_key(key, value)
            local ok, err, force = dogs:set(key, value)
            if ok then
                ngx.print("successfully set ", key)
                if force then
                    ngx.say(" with force.")
                else
                    ngx.say(".")
                end
            else
                ngx.say("failed to set ", key, ": ", err)
            end
        end

        local function safe_set_key(key, value)
            local ok, err = dogs:safe_set(key, value)
            if ok then
                ngx.say("successfully safe set ", key)
            else
                ngx.say("failed to safe set ", key, ": ", err)
            end
        end

        for i = 1, 1 do
            for j = 1, 63 do
                dogs:set("foo" .. j, string.rep("a", 5))
            end
            set_key("bar", string.rep("a", 4000))

            --[[
            for j = 1, 50 do
                dogs:delete("foo" .. j)
            end
            ]]

            safe_set_key("baz", string.rep("b", 8100))
            check_key("bar")

            ngx.say("delete bar")
            dogs:delete("bar")

            safe_set_key("baz", string.rep("b", 8100))
        end

        collectgarbage()
    }
--- stap
global first_time = 1
global active = 1

F(ngx_stream_lua_shdict_init_zone) {
    active = 0
}

F(ngx_stream_lua_shdict_init_zone).return {
    active = 1
}

F(ngx_slab_alloc_pages) {
    if (first_time) {
        //printf("slab max size: %d\n", @var("ngx_slab_max_size"))
        printf("total pages: %d\n", $pool->pages->slab)
        first_time = 0
    }
    if (active) {
        printf("alloc pages: %d", $pages)
        //print_ubacktrace()
    } else {
        printf("init zone alloc pages: %d", $pages)
    }
}

F(ngx_slab_alloc_pages).return {
    if ($return) {
        printf(" ok\n")

    } else {
        printf(" NOT OK\n")
    }
}

F(ngx_slab_free_pages) {
    printf("free pages: %d\n", $pages)
}

--- stap_out
total pages: 4
init zone alloc pages: 1 ok
init zone alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 NOT OK

--- stream_response
successfully set bar.
failed to safe set baz: no memory
found bar: 4000
delete bar
failed to safe set baz: no memory

--- no_error_log
[error]



=== TEST 9: cannot merge in-used big slabs page (forward)
--- stream_config
    lua_shared_dict dogs 20k;
--- stream_server_config
    content_by_lua_block {
        local dogs = ngx.shared.dogs

        local function check_key(key)
            local res, err = dogs:get(key)
            if res then
                ngx.say("found ", key, ": ", #res)
            else
                if not err then
                    ngx.say(key, " not found")
                else
                    ngx.say("failed to fetch key: ", err)
                end
            end
        end

        local function set_key(key, value)
            local ok, err, force = dogs:set(key, value)
            if ok then
                ngx.print("successfully set ", key)
                if force then
                    ngx.say(" with force.")
                else
                    ngx.say(".")
                end
            else
                ngx.say("failed to set ", key, ": ", err)
            end
        end

        local function safe_set_key(key, value)
            local ok, err = dogs:safe_set(key, value)
            if ok then
                ngx.say("successfully safe set ", key)
            else
                ngx.say("failed to safe set ", key, ": ", err)
            end
        end

        for i = 1, 1 do
            set_key("bar", string.rep("a", 4000))
            for j = 1, 50 do
                dogs:set("foo" .. j, string.rep("a", 5))
            end

            --[[
            for j = 1, 50 do
                dogs:delete("foo" .. j)
            end
            ]]

            safe_set_key("baz", string.rep("b", 8100))
            check_key("bar")

            ngx.say("delete bar")
            dogs:delete("bar")

            safe_set_key("baz", string.rep("b", 8100))
        end

        collectgarbage()
    }
--- stap
global first_time = 1
global active = 1

F(ngx_stream_lua_shdict_init_zone) {
    active = 0
}

F(ngx_stream_lua_shdict_init_zone).return {
    active = 1
}

F(ngx_slab_alloc_pages) {
    if (first_time) {
        //printf("slab max size: %d\n", @var("ngx_slab_max_size"))
        printf("total pages: %d\n", $pool->pages->slab)
        first_time = 0
    }
    if (active) {
        printf("alloc pages: %d", $pages)
        //print_ubacktrace()
    } else {
        printf("init zone alloc pages: %d", $pages)
    }
}

F(ngx_slab_alloc_pages).return {
    if ($return) {
        printf(" ok\n")

    } else {
        printf(" NOT OK\n")
    }
}

F(ngx_slab_free_pages) {
    printf("free pages: %d\n", $pages)
}

--- stap_out
total pages: 4
init zone alloc pages: 1 ok
init zone alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 1 ok
alloc pages: 2 NOT OK
free pages: 1
alloc pages: 2 NOT OK

--- stream_response
successfully set bar.
failed to safe set baz: no memory
found bar: 4000
delete bar
failed to safe set baz: no memory

--- no_error_log
[error]



=== TEST 10: fuzz testing
--- stream_config
    lua_shared_dict dogs 200k;
--- stream_server_config
    content_by_lua_block {
        local rand = math.random
        local dogs = ngx.shared.dogs
        local maxsz = 9000
        local maxkeyidx = 30
        local rep = string.rep

        math.randomseed(ngx.time())
        for i = 1, 30000 do
            local key = "mylittlekey" .. rand(maxkeyidx)
            local ok, err = dogs:get(key)
            if not ok or rand() > 0.6 then
                sz = rand(maxsz)
                val = rep("a", sz)
                local ok, err, forcible = dogs:set(key, val)
                if err then
                    ngx.log(ngx.ERR, "failed to set key: ", err)
                    -- return
                end
                if forcible then
                    -- error("forcible")
                end
            end
        end
        ngx.say("ok")
        collectgarbage()
    }
--- stream_response
ok

--- no_error_log
[error]
--- timeout: 60
