1#!/usr/bin/env escript
2%% -*- erlang -*-
3%%! -pa ./src/couchdb -sasl errlog_type error -noshell -smp enable
4
5% Licensed under the Apache License, Version 2.0 (the "License"); you may not
6% use this file except in compliance with the License. You may obtain a copy of
7% the License at
8%
9%   http://www.apache.org/licenses/LICENSE-2.0
10%
11% Unless required by applicable law or agreed to in writing, software
12% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14% License for the specific language governing permissions and limitations under
15% the License.
16
17filename() -> "./test/etap/temp.024".
18
19
20main(_) ->
21    test_util:init_code_path(),
22    etap:plan(11),
23    case (catch test()) of
24        ok ->
25            etap:end_tests();
26        Other ->
27            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
28            etap:bail()
29    end,
30    ok.
31
32
33test() ->
34    couch_file_write_guard:sup_start_link(),
35    N = 77651,
36    {ok, Btree, Fd} = create_btree(N),
37    lists:foreach(fun(I) ->
38        many_items_tree_test(Btree, I)
39    end, [1, 6, 666, 669, 9999, 15001, 22228, 50703, 77000, 77651]),
40    ok = couch_file:close(Fd),
41    ok = file:delete(filename()).
42
43
44create_btree(N) ->
45    ReduceFun = fun
46        (reduce, KVs) ->
47            length(KVs);
48        (rereduce, Reds) ->
49            lists:sum(Reds)
50    end,
51
52    {ok, Fd} = couch_file:open(filename(), [create, overwrite]),
53    {ok, Btree} = couch_btree:open(nil, Fd, [{reduce, ReduceFun}]),
54
55    KVs = [{I, I * I} || I <- lists:seq(1, N)],
56
57    {ok, Btree2} = couch_btree:add_remove(Btree, KVs, []),
58    ok = couch_file:flush(Fd),
59
60    {ok, FullRed} = couch_btree:full_reduce(Btree2),
61    etap:is(FullRed, N, "Initial reduce value equals N"),
62
63    {ok, Btree2, Fd}.
64
65
66many_items_tree_test(Btree, ItemNumber) ->
67    Acc0 = {1, undefined},
68    FoldFun = fun
69        (value, KV, _Reds, {I, undefined}) ->
70            case I == ItemNumber of
71            true ->
72                {stop, {I, KV}};
73            false ->
74                {ok, {I + 1, undefined}}
75            end;
76        (branch, _K, Red, {I, undefined}) ->
77            I2 = I + Red,
78            case I2 >= ItemNumber of
79            true ->
80                {ok, {I, undefined}};
81            false ->
82                {skip, {I2, undefined}}
83            end
84    end,
85    {ok, _, FinalAcc} = couch_btree:fold(Btree, FoldFun, Acc0, []),
86    io:format("FinalAcc: ~p~n", [FinalAcc]),
87    etap:is(FinalAcc,
88            {ItemNumber, {ItemNumber, ItemNumber * ItemNumber}},
89            "Got expected final acc").
90