diff options
Diffstat (limited to 'src/couch_replicator/test/eunit/couch_replicator_test_helper.erl')
-rw-r--r-- | src/couch_replicator/test/eunit/couch_replicator_test_helper.erl | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/couch_replicator/test/eunit/couch_replicator_test_helper.erl b/src/couch_replicator/test/eunit/couch_replicator_test_helper.erl new file mode 100644 index 000000000..fd0409164 --- /dev/null +++ b/src/couch_replicator/test/eunit/couch_replicator_test_helper.erl @@ -0,0 +1,135 @@ +-module(couch_replicator_test_helper). + +-include_lib("couch/include/couch_eunit.hrl"). +-include_lib("couch/include/couch_db.hrl"). +-include_lib("couch_replicator/src/couch_replicator.hrl"). + +-export([ + compare_dbs/2, + compare_dbs/3, + db_url/1, + replicate/1, + get_pid/1, + replicate/2 +]). + + +compare_dbs(Source, Target) -> + compare_dbs(Source, Target, []). + + +compare_dbs(Source, Target, ExceptIds) -> + {ok, SourceDb} = couch_db:open_int(Source, []), + {ok, TargetDb} = couch_db:open_int(Target, []), + + Fun = fun(FullDocInfo, Acc) -> + {ok, DocSource} = couch_db:open_doc(SourceDb, FullDocInfo), + Id = DocSource#doc.id, + case lists:member(Id, ExceptIds) of + true -> + ?assertEqual(not_found, couch_db:get_doc_info(TargetDb, Id)); + false -> + {ok, TDoc} = couch_db:open_doc(TargetDb, Id), + compare_docs(DocSource, TDoc) + end, + {ok, Acc} + end, + + {ok, _} = couch_db:fold_docs(SourceDb, Fun, [], []), + ok = couch_db:close(SourceDb), + ok = couch_db:close(TargetDb). + + +compare_docs(Doc1, Doc2) -> + ?assertEqual(Doc1#doc.body, Doc2#doc.body), + #doc{atts = Atts1} = Doc1, + #doc{atts = Atts2} = Doc2, + ?assertEqual(lists:sort([couch_att:fetch(name, Att) || Att <- Atts1]), + lists:sort([couch_att:fetch(name, Att) || Att <- Atts2])), + FunCompareAtts = fun(Att) -> + AttName = couch_att:fetch(name, Att), + {ok, AttTarget} = find_att(Atts2, AttName), + SourceMd5 = att_md5(Att), + TargetMd5 = att_md5(AttTarget), + case AttName of + <<"att1">> -> + ?assertEqual(gzip, couch_att:fetch(encoding, Att)), + ?assertEqual(gzip, couch_att:fetch(encoding, AttTarget)), + DecSourceMd5 = att_decoded_md5(Att), + DecTargetMd5 = att_decoded_md5(AttTarget), + ?assertEqual(DecSourceMd5, DecTargetMd5); + _ -> + ?assertEqual(identity, couch_att:fetch(encoding, AttTarget)), + ?assertEqual(identity, couch_att:fetch(encoding, AttTarget)) + end, + ?assertEqual(SourceMd5, TargetMd5), + ?assert(is_integer(couch_att:fetch(disk_len, Att))), + ?assert(is_integer(couch_att:fetch(att_len, Att))), + ?assert(is_integer(couch_att:fetch(disk_len, AttTarget))), + ?assert(is_integer(couch_att:fetch(att_len, AttTarget))), + ?assertEqual(couch_att:fetch(disk_len, Att), + couch_att:fetch(disk_len, AttTarget)), + ?assertEqual(couch_att:fetch(att_len, Att), + couch_att:fetch(att_len, AttTarget)), + ?assertEqual(couch_att:fetch(type, Att), + couch_att:fetch(type, AttTarget)), + ?assertEqual(couch_att:fetch(md5, Att), + couch_att:fetch(md5, AttTarget)) + end, + lists:foreach(FunCompareAtts, Atts1). + + +find_att([], _Name) -> + nil; +find_att([Att | Rest], Name) -> + case couch_att:fetch(name, Att) of + Name -> + {ok, Att}; + _ -> + find_att(Rest, Name) + end. + + +att_md5(Att) -> + Md50 = couch_att:foldl( + Att, + fun(Chunk, Acc) -> couch_hash:md5_hash_update(Acc, Chunk) end, + couch_hash:md5_hash_init()), + couch_hash:md5_hash_final(Md50). + +att_decoded_md5(Att) -> + Md50 = couch_att:foldl_decode( + Att, + fun(Chunk, Acc) -> couch_hash:md5_hash_update(Acc, Chunk) end, + couch_hash:md5_hash_init()), + couch_hash:md5_hash_final(Md50). + +db_url(DbName) -> + iolist_to_binary([ + "http://", config:get("httpd", "bind_address", "127.0.0.1"), + ":", integer_to_list(mochiweb_socket_server:get(couch_httpd, port)), + "/", DbName + ]). + +get_pid(RepId) -> + Pid = global:whereis_name({couch_replicator_scheduler_job,RepId}), + ?assert(is_pid(Pid)), + Pid. + +replicate(Source, Target) -> + replicate({[ + {<<"source">>, Source}, + {<<"target">>, Target} + ]}). + +replicate({[_ | _]} = RepObject) -> + {ok, Rep} = couch_replicator_utils:parse_rep_doc(RepObject, ?ADMIN_USER), + ok = couch_replicator_scheduler:add_job(Rep), + couch_replicator_scheduler:reschedule(), + Pid = get_pid(Rep#rep.id), + MonRef = erlang:monitor(process, Pid), + receive + {'DOWN', MonRef, process, Pid, _} -> + ok + end, + ok = couch_replicator_scheduler:remove_job(Rep#rep.id). |