summaryrefslogtreecommitdiff
path: root/src/couch_views/test/couch_views_encoding_test.erl
blob: d15f616cb36639989f9fc5cf7116deecf0a1c736 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
% Licensed 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.

-module(couch_views_encoding_test).

-include_lib("eunit/include/eunit.hrl").

val_encoding_test() ->
    Values = [
        null,
        true,
        1.0,
        <<"a">>,
        {[{<<"a">>, 1.0}, {<<"b">>, <<"hello">>}]}
    ],
    lists:foreach(fun (Val) ->
        EncVal = couch_views_encoding:encode(Val),
        ?assertEqual(Val, couch_views_encoding:decode(EncVal))
    end, Values).


setup() ->
    % Load the ICU driver for couch_util:get_sort_key/1
    {ok, CfgPid} = gen_server:start_link(config, [], []),
    {ok, DrvPid} = gen_server:start_link(couch_drv, [], []),
    {CfgPid, DrvPid}.


teardown({CfgPid, DrvPid}) ->
    unlink(CfgPid),
    unlink(DrvPid),
    exit(CfgPid, kill),
    exit(DrvPid, kill).


correct_ordering_test_() ->
    {
        setup,
        fun setup/0,
        fun teardown/1,
        [
            fun t_correct_ordering/0
        ]
    }.


t_correct_ordering() ->
    ?_test(begin
        Ordered = [
            %  Special values sort before all other types
            null,
            false,
            true,

            % Then numbers
            1,
            2,
            3.0,
            4,

            % Then text, case sensitive
            <<"a">>,
            <<"A">>,
            <<"aa">>,
            <<"b">>,
            <<"B">>,
            <<"ba">>,
            <<"bb">>,

            % Then arrays, compared element by element until different.
            % Longer arrays sort after their prefixes
            [<<"a">>],
            [<<"b">>],
            [<<"b">>, <<"c">>],
            [<<"b">>, <<"c">>, <<"a">>],
            [<<"b">>, <<"d">>],
            [<<"b">>, <<"d">>, <<"e">>],

            % Then objects, compared each key value in the list until different.
            % Larger objects sort after their subset objects
            {[{<<"a">>, 1}]},
            {[{<<"a">>, 2}]},
            {[{<<"b">>, 1}]},
            {[{<<"b">>, 2}]},

            % Member order does matter for collation
            {[{<<"b">>, 2}, {<<"a">>, 1}]},
            {[{<<"b">>, 2}, {<<"c">>, 2}]}
        ],

        Encoded = lists:map(fun(Elem) ->
            K = couch_views_encoding:encode(Elem, key),
            V = couch_views_encoding:encode(Elem, value),
            {K, V}
        end, Ordered),
        Shuffled = shuffle(Encoded),
        Reordered = lists:sort(Shuffled),

        lists:foreach(fun({Original, {_K, ViewEncoded}}) ->
            ?assertEqual(Original, couch_views_encoding:decode(ViewEncoded))
        end, lists:zip(Ordered, Reordered))
    end).


shuffle(List) when is_list(List) ->
    Tagged = [{rand:uniform(), Item} || Item <- List],
    {_, Randomized} = lists:unzip(lists:sort(Tagged)),
    Randomized.