1#!/usr/bin/env escript
2%% -*- erlang -*-
3%%! -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
17-include_lib("../include/couch_spatial.hrl").
18-include_lib("couch_set_view/include/couch_set_view.hrl").
19
20% from couch_db.hrl
21-define(MIN_STR, <<>>).
22-define(MAX_STR, <<255>>).
23
24
25test_set_name() -> <<"couch_test_spatial_view_initial_build">>.
26num_set_partitions() -> 4.
27ddoc_id() -> <<"_design/test">>.
28num_docs() -> 1024.  % keep it a multiple of num_set_partitions()
29
30
31main(_) ->
32    test_util:init_code_path(),
33
34    etap:plan(2),
35    case (catch test()) of
36        ok ->
37            etap:end_tests();
38        Other ->
39            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
40            etap:bail(Other)
41    end,
42    %init:stop(),
43    %receive after infinity -> ok end,
44    ok.
45
46
47test() ->
48    spatial_test_util:start_server(test_set_name()),
49
50    etap:diag("Testing inital build of spatial views"),
51
52    test_spatial_query(),
53
54    % A clean shutdown is not implemented yet, it will come in future commits
55    couch_set_view_test_util:delete_set_dbs(test_set_name(), num_set_partitions()),
56    spatial_test_util:stop_server(),
57    ok.
58
59
60test_spatial_query() ->
61    setup_test(),
62    ok = configure_spatial_group(ddoc_id()),
63
64    {ok, Rows} = (catch query_spatial_view(<<"test">>)),
65    etap:is(length(Rows), num_docs(),
66        "Got all view rows (" ++ integer_to_list(num_docs()) ++ ")"),
67    verify_rows(Rows),
68
69    shutdown_group(),
70    ok.
71
72
73verify_rows(Rows) ->
74    DocList = lists:map(fun(Doc) ->
75        {[{<<"meta">>, {[{<<"id">>, DocId}]}},
76          {<<"json">>, {[{<<"value">>, Value} | _Rest]}}]} = Doc,
77        {DocId,
78         <<"\"val", (list_to_binary(integer_to_list(Value)))/binary, "\"">>}
79    end, create_docs(1, num_docs())),
80
81    RowsWithoutKey = [{DocId, Value} ||
82        {Key, DocId, {_PartId, Value, nil}} <- Rows],
83    etap:is(lists:sort(RowsWithoutKey), lists:sort(DocList),
84            "Returned correct rows").
85
86
87query_spatial_view(ViewName) ->
88    etap:diag("Querying spatial view " ++ binary_to_list(ddoc_id()) ++ "/" ++
89        binary_to_list(ViewName)),
90    Req = #set_view_group_req{
91        stale = false
92    },
93    {ok, View, Group, _} = spatial_view:get_spatial_view(
94        test_set_name(), ddoc_id(), ViewName, Req),
95
96    FoldFun = fun({{Key, DocId}, Value}, Acc) ->
97        {ok, [{Key, DocId, Value} | Acc]}
98    end,
99    ViewArgs = #spatial_query_args{},
100
101    {ok, _, Rows} = couch_set_view:fold(Group, View, FoldFun, [], ViewArgs),
102    couch_set_view:release_group(Group),
103    {ok, lists:reverse(Rows)}.
104
105
106setup_test() ->
107    couch_set_view_test_util:delete_set_dbs(test_set_name(), num_set_partitions()),
108    couch_set_view_test_util:create_set_dbs(test_set_name(), num_set_partitions()),
109
110    DDoc = {[
111        {<<"meta">>, {[{<<"id">>, ddoc_id()}]}},
112        {<<"json">>, {[
113            {<<"spatial">>, {[
114                {<<"test">>, <<"function(doc, meta) { emit([[doc.min, doc.max], [doc.min2, doc.max2]], 'val'+doc.value); }">>}
115            ]}}
116        ]}}
117    ]},
118    populate_set(DDoc).
119
120
121create_docs(From, To) ->
122    rand:seed(exrop, {91, 1, 11}),
123    lists:map(
124        fun(I) ->
125            RandomMin = rand:uniform(2000),
126            RandomMax = RandomMin + rand:uniform(167),
127            RandomMin2 = rand:uniform(1769),
128            RandomMax2 = RandomMin2 + rand:uniform(132),
129            {[
130              {<<"meta">>, {[{<<"id">>, iolist_to_binary(["doc", integer_to_list(I)])}]}},
131              {<<"json">>, {[
132                             {<<"value">>, I},
133                             {<<"min">>, RandomMin},
134                             {<<"max">>, RandomMax},
135                             {<<"min2">>, RandomMin2},
136                             {<<"max2">>, RandomMax2}
137                            ]}}
138            ]}
139        end,
140        lists:seq(From, To)).
141
142
143populate_set(DDoc) ->
144    etap:diag("Populating the " ++ integer_to_list(num_set_partitions()) ++
145        " databases with " ++ integer_to_list(num_docs()) ++ " documents"),
146    ok = couch_set_view_test_util:update_ddoc(test_set_name(), DDoc),
147    DocList = create_docs(1, num_docs()),
148    ok = couch_set_view_test_util:populate_set_sequentially(
149        test_set_name(),
150        lists:seq(0, num_set_partitions() - 1),
151        DocList).
152
153
154configure_spatial_group(DDocId) ->
155    etap:diag("Configuring spatial view group"),
156    Params = #set_view_params{
157        max_partitions = num_set_partitions(),
158        active_partitions = lists:seq(0, num_set_partitions()-1),
159        passive_partitions = [],
160        use_replica_index = false
161    },
162    try
163        ok = couch_set_view:define_group(
164            spatial_view, test_set_name(), DDocId, Params)
165    catch _:Error ->
166        Error
167    end.
168
169
170% A clean shutdown is not implemented yet, it will come in future commits
171shutdown_group() ->
172    GroupPid = couch_set_view:get_group_pid(
173        spatial_view, test_set_name(), ddoc_id(), prod),
174    couch_set_view_test_util:delete_set_dbs(test_set_name(), num_set_partitions()),
175    MonRef = erlang:monitor(process, GroupPid),
176    receive
177    {'DOWN', MonRef, _, _, _} ->
178        ok
179    after 10000 ->
180        etap:bail("Timeout waiting for group shutdown")
181    end.
182