summaryrefslogtreecommitdiff
path: root/src/couch_replicator/test/eunit/couch_replicator_missing_stubs_tests.erl
blob: e672c76b7d6e7c991e44b3a4918605d84d758164 (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
% 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_replicator_missing_stubs_tests).

-include_lib("couch/include/couch_eunit.hrl").
-include_lib("couch/include/couch_db.hrl").
-include_lib("fabric/test/fabric2_test.hrl").


-define(REVS_LIMIT, 3).


missing_stubs_test_() ->
    {
        "Replicate docs with missing stubs (COUCHDB-1365)",
        {
            setup,
            fun couch_replicator_test_helper:start_couch/0,
            fun couch_replicator_test_helper:stop_couch/1,
            {
                foreach,
                fun setup/0,
                fun teardown/1,
                [
                    ?TDEF_FE(should_replicate_docs_with_missed_att_stubs, 60)
                ]
            }
        }
    }.


setup() ->
    Source = couch_replicator_test_helper:create_db(),
    populate_db(Source),
    Target = couch_replicator_test_helper:create_db(),
    {Source, Target}.


teardown({Source, Target}) ->
    couch_replicator_test_helper:delete_db(Source),
    couch_replicator_test_helper:delete_db(Target).


should_replicate_docs_with_missed_att_stubs({Source, Target}) ->
    {ok, TargetDb} = fabric2_db:open(Target, [?ADMIN_CTX]),
    ?assertEqual(ok, fabric2_db:set_revs_limit(TargetDb, ?REVS_LIMIT)),

    ?assertMatch({ok, _},
        couch_replicator_test_helper:replicate(Source, Target)),
    ?assertEqual(ok, couch_replicator_test_helper:compare_dbs(Source, Target)),

    ok = update_db_docs(Source, ?REVS_LIMIT * 2),

    ?assertMatch({ok, _},
        couch_replicator_test_helper:replicate(Source, Target)),
    ?assertEqual(ok, couch_replicator_test_helper:compare_dbs(Source, Target)).


populate_db(DbName) ->
    AttData = crypto:strong_rand_bytes(6000),
    Doc = #doc{
        id = <<"doc1">>,
        atts = [
            couch_att:new([
                {name, <<"doc1_att1">>},
                {type, <<"application/foobar">>},
                {att_len, byte_size(AttData)},
                {data, AttData}
            ])
        ]
    },
    couch_replicator_test_helper:create_docs(DbName, [Doc]).


update_db_docs(DbName, Times) ->
    {ok, Db} = fabric2_db:open(DbName, [?ADMIN_CTX]),
    FoldFun = fun
        ({meta, _Meta}, Acc) ->
            {ok, Acc};
        (complete, Acc) ->
            {ok, Acc};
        ({row, Row}, Acc) ->
            {_, DocId} = lists:keyfind(id, 1, Row),
            ok = update_doc(DbName, DocId, Times),
            {ok, Acc}
    end,
    Opts = [{restart_tx, true}],
    {ok, _} = fabric2_db:fold_docs(Db, FoldFun, ok, Opts),
    ok.


update_doc(_DbName, _DocId, 0) ->
    ok;

update_doc(DbName, DocId, Times) ->
    {ok, Db} = fabric2_db:open(DbName, [?ADMIN_CTX]),
    {ok, Doc} = fabric2_db:open_doc(Db, DocId, []),
    #doc{revs = {Pos, [Rev | _]}} = Doc,
    Val = base64:encode(crypto:strong_rand_bytes(100)),
    Doc1 = Doc#doc{
        revs = {Pos, [Rev]},
        body = {[{<<"value">>, Val}]}
    },
    {ok, _} = fabric2_db:update_doc(Db, Doc1),
    update_doc(DbName, DocId, Times - 1).