From 58ad7ad6c330bf65b89e0f5e4a790d14510d3ce7 Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Thu, 11 Jun 2009 01:59:56 +0000 Subject: Integrating more ETAP tests from Bob Dionne. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@783600 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/010-file-basics.t | 2 +- test/etap/030-doc-from-json.t | 2 +- test/etap/040-util.t | 72 +++++++++++++++++++++ test/etap/050-stream.t | 75 ++++++++++++++++++++++ test/etap/060-kt-merging.t | 128 ++++++++++++++++++++++++++++++++++++++ test/etap/061-kt-missing-leaves.t | 53 ++++++++++++++++ test/etap/062-kt-remove-leaves.t | 57 +++++++++++++++++ test/etap/063-kt-get-leaves.t | 86 +++++++++++++++++++++++++ test/etap/064-kt-counting.t | 34 ++++++++++ test/etap/065-kt-stemming.t | 30 +++++++++ test/etap/070-couch-db.t | 63 +++++++++++++++++++ 11 files changed, 600 insertions(+), 2 deletions(-) create mode 100644 test/etap/040-util.t create mode 100644 test/etap/050-stream.t create mode 100644 test/etap/060-kt-merging.t create mode 100644 test/etap/061-kt-missing-leaves.t create mode 100644 test/etap/062-kt-remove-leaves.t create mode 100644 test/etap/063-kt-get-leaves.t create mode 100644 test/etap/064-kt-counting.t create mode 100644 test/etap/065-kt-stemming.t create mode 100644 test/etap/070-couch-db.t (limited to 'test/etap') diff --git a/test/etap/010-file-basics.t b/test/etap/010-file-basics.t index 7c1c80eb..9033317f 100755 --- a/test/etap/010-file-basics.t +++ b/test/etap/010-file-basics.t @@ -81,4 +81,4 @@ test() -> etap:is(ok, couch_file:close(Fd), "Files close properly."), - ok. \ No newline at end of file + ok. diff --git a/test/etap/030-doc-from-json.t b/test/etap/030-doc-from-json.t index 13d11442..242591ed 100755 --- a/test/etap/030-doc-from-json.t +++ b/test/etap/030-doc-from-json.t @@ -206,4 +206,4 @@ test_from_json_errors() -> _:_ -> etap:ok(true, Mesg) end end, Cases), - ok. \ No newline at end of file + ok. diff --git a/test/etap/040-util.t b/test/etap/040-util.t new file mode 100644 index 00000000..a6b7df33 --- /dev/null +++ b/test/etap/040-util.t @@ -0,0 +1,72 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +main(_) -> + code:add_pathz("src/couchdb"), + application:start(crypto), + + etap:plan(11), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + % to_existing_atom + etap:is(true, couch_util:to_existing_atom(true), "An atom is an atom."), + etap:is(foo, couch_util:to_existing_atom(<<"foo">>), + "A binary foo is the atom foo."), + etap:is(foobarbaz, couch_util:to_existing_atom("foobarbaz"), + "A list of atoms is one munged atom."), + + % terminate_linked + Self = self(), + spawn(fun() -> + ChildPid = spawn_link(fun() -> receive shutdown -> ok end end), + couch_util:terminate_linked(normal), + Self ! {pid, ChildPid} + end), + receive + {pid, Pid} -> + etap:ok(not is_process_alive(Pid), "why wont this work?") + end, + + % new_uuid + etap:isnt(couch_util:new_uuid(), couch_util:new_uuid(), + "A guid ought to be unique."), + + % implode + etap:is([1, 38, 2, 38, 3], couch_util:implode([1,2,3],"&"), + "use & as separator in list."), + + % trim + Strings = [" foo", "foo ", "\tfoo", " foo ", "foo\t", "foo\n", "\nfoo"], + etap:ok(lists:all(fun(S) -> couch_util:trim(S) == "foo" end, Strings), + "everything here trimmed should be foo."), + + % abs_pathname + {ok, Cwd} = file:get_cwd(), + etap:is(Cwd ++ "/foo", couch_util:abs_pathname("./foo"), + "foo is in this directory."), + + % should_flush + etap:ok(not couch_util:should_flush(), + "Not using enough memory to flush."), + AcquireMem = fun() -> + IntsToAGazillion = lists:seq(1, 200000), + LotsOfData = lists:map( + fun(Int) -> {Int, <<"foobar">>} end, + lists:seq(1, 200000)), + etap:ok(couch_util:should_flush(), + "Allocation 200K tuples puts us above the memory threshold.") + end, + AcquireMem(), + + etap:ok(not couch_util:should_flush(), + "Checking to flush invokes GC."), + + ok. diff --git a/test/etap/050-stream.t b/test/etap/050-stream.t new file mode 100644 index 00000000..41aa9754 --- /dev/null +++ b/test/etap/050-stream.t @@ -0,0 +1,75 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +main(_) -> + code:add_pathz("src/couchdb"), + etap:plan(unknown), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +read_all(Fd, PosList) -> + Data = couch_stream:foldl(Fd, PosList, fun(Bin, Acc) -> [Bin, Acc] end, []), + iolist_to_binary(Data). + +test() -> + {ok, Fd} = couch_file:open("test/etap/temp.050", [create,overwrite]), + {ok, Stream} = couch_stream:open(Fd), + + etap:is(ok, couch_stream:write(Stream, <<"food">>), + "Writing to streams works."), + + etap:is(ok, couch_stream:write(Stream, <<"foob">>), + "Consecutive writing to streams works."), + + etap:is(ok, couch_stream:write(Stream, <<>>), + "Writing an empty binary does nothing."), + + {Ptrs, Length} = couch_stream:close(Stream), + etap:is(Ptrs, [0], "Close returns the file pointers."), + etap:is(Length, 8, "Close also returns the number of bytes written."), + etap:is(<<"foodfoob">>, read_all(Fd, Ptrs), "Returned pointers are valid."), + + % Remeber where we expect the pointer to be. + {ok, ExpPtr} = couch_file:bytes(Fd), + {ok, Stream2} = couch_stream:open(Fd), + OneBits = <<1:(8*10)>>, + etap:is(ok, couch_stream:write(Stream2, OneBits), + "Successfully wrote 80 1 bits."), + + ZeroBits = <<0:(8*10)>>, + etap:is(ok, couch_stream:write(Stream2, ZeroBits), + "Successfully wrote 80 0 bits."), + + {Ptrs2, Length2} = couch_stream:close(Stream2), + etap:is(Ptrs2, [ExpPtr], "Closing stream returns the file pointers."), + etap:is(Length2, 20, "Length written is 160 bytes."), + + AllBits = iolist_to_binary([OneBits,ZeroBits]), + etap:is(AllBits, read_all(Fd, Ptrs2), "Returned pointers are valid."), + + % Stream more the 4K chunk size. + {ok, ExpPtr2} = couch_file:bytes(Fd), + {ok, Stream3} = couch_stream:open(Fd), + Acc2 = lists:foldl(fun(_, Acc) -> + Data = <<"a1b2c">>, + couch_stream:write(Stream3, Data), + [Data | Acc] + end, [], lists:seq(1, 1024)), + {Ptrs3, Length3} = couch_stream:close(Stream3), + + % 4095 because of 5 * 4096 rem 5 (last write before exceeding threshold) + % + 5 puts us over the threshold + % + 4 bytes for the term_to_binary adding a length header + % + 1 byte every 4K for tail append headers + SecondPtr = ExpPtr2 + 4095 + 5 + 4 + 1, + etap:is(Ptrs3, [ExpPtr2, SecondPtr], "Pointers every 4K bytes."), + etap:is(Length3, 5120, "Wrote the expected 5K bytes."), + + couch_file:close(Fd), + ok. diff --git a/test/etap/060-kt-merging.t b/test/etap/060-kt-merging.t new file mode 100644 index 00000000..5616b8ef --- /dev/null +++ b/test/etap/060-kt-merging.t @@ -0,0 +1,128 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +main(_) -> + code:add_pathz("src/couchdb"), + etap:plan(unknown), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + EmptyTree = [], + One = [{0, {"1","foo",[]}}], + TwoSibs = [{0, {"1","foo",[]}}, + {0, {"2","foo",[]}}], + OneChild = [{0, {"1","foo",[{"1a", "bar", []}]}}], + TwoChild = [{0, {"1","foo", [{"1a", "bar", [{"1aa", "bar", []}]}]}}], + TwoChildSibs = [{0, {"1","foo", [{"1a", "bar", []}, + {"1b", "bar", []}]}}], + TwoChildSibs2 = [{0, {"1","foo", [{"1a", "bar", []}, + {"1b", "bar", [{"1bb", "boo", []}]}]}}], + Stemmed1b = [{1, {"1a", "bar", []}}], + Stemmed1a = [{1, {"1a", "bar", [{"1aa", "bar", []}]}}], + Stemmed1aa = [{2, {"1aa", "bar", []}}], + Stemmed1bb = [{2, {"1bb", "boo", []}}], + + etap:is( + {EmptyTree, no_conflicts}, + couch_key_tree:merge(EmptyTree, EmptyTree), + "Merging two empty trees yields an empty tree." + ), + + etap:is( + {One, no_conflicts}, + couch_key_tree:merge(EmptyTree, One), + "The empty tree is the identity for merge." + ), + + etap:is( + {One, no_conflicts}, + couch_key_tree:merge(One, EmptyTree), + "Merging is commutative." + ), + + etap:is( + {TwoSibs, no_conflicts}, + couch_key_tree:merge(One, TwoSibs), + "Merging a prefix of a tree with the tree yields the tree." + ), + + etap:is( + {One, no_conflicts}, + couch_key_tree:merge(One, One), + "Merging is reflexive." + ), + + etap:is( + {TwoChild, no_conflicts}, + couch_key_tree:merge(TwoChild, TwoChild), + "Merging two children is still reflexive." + ), + + etap:is( + {TwoChildSibs, no_conflicts}, + couch_key_tree:merge(TwoChildSibs, TwoChildSibs), + "Merging a tree to itself is itself."), + + etap:is( + {TwoChildSibs, no_conflicts}, + couch_key_tree:merge(TwoChildSibs, Stemmed1b), + "Merging a tree with a stem." + ), + + etap:is( + {TwoChildSibs, no_conflicts}, + couch_key_tree:merge(Stemmed1b, TwoChildSibs), + "Merging in the opposite direction." + ), + + etap:is( + {TwoChildSibs2, no_conflicts}, + couch_key_tree:merge(TwoChildSibs2, Stemmed1bb), + "Merging a stem at a deeper level." + ), + + etap:is( + {TwoChildSibs2, no_conflicts}, + couch_key_tree:merge(Stemmed1bb, TwoChildSibs2), + "Merging a deeper level in opposite order." + ), + + etap:is( + {TwoChild, no_conflicts}, + couch_key_tree:merge(TwoChild, Stemmed1aa), + "Merging a single tree with a deeper stem." + ), + + etap:is( + {TwoChild, no_conflicts}, + couch_key_tree:merge(TwoChild, Stemmed1a), + "Merging a larger stem." + ), + + etap:is( + {Stemmed1a, no_conflicts}, + couch_key_tree:merge(Stemmed1a, Stemmed1aa), + "More merging." + ), + + Expect1 = OneChild ++ Stemmed1aa, + etap:is( + {Expect1, conflicts}, + couch_key_tree:merge(OneChild, Stemmed1aa), + "Merging should create conflicts." + ), + + etap:is( + {TwoChild, no_conflicts}, + couch_key_tree:merge(Expect1, TwoChild), + "Merge should have no conflicts." + ), + + ok. diff --git a/test/etap/061-kt-missing-leaves.t b/test/etap/061-kt-missing-leaves.t new file mode 100644 index 00000000..78d95efa --- /dev/null +++ b/test/etap/061-kt-missing-leaves.t @@ -0,0 +1,53 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +main(_) -> + code:add_pathz("src/couchdb"), + etap:plan(unknown), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + TwoChildSibs = [{0, {"1","foo", [{"1a", "bar", []}, {"1b", "bar", []}]}}], + Stemmed1 = [{1, {"1a", "bar", [{"1aa", "bar", []}]}}], + Stemmed2 = [{2, {"1aa", "bar", []}}], + + etap:is( + [], + couch_key_tree:find_missing(TwoChildSibs, [{0,"1"}, {1,"1a"}]), + "Look for missing keys." + ), + + etap:is( + [{0, "10"}, {100, "x"}], + couch_key_tree:find_missing( + TwoChildSibs, + [{0,"1"}, {0, "10"}, {1,"1a"}, {100, "x"}] + ), + "Look for missing keys." + ), + + etap:is( + [{0, "1"}, {100, "x"}], + couch_key_tree:find_missing( + Stemmed1, + [{0,"1"}, {1,"1a"}, {100, "x"}] + ), + "Look for missing keys." + ), + etap:is( + [{0, "1"}, {1,"1a"}, {100, "x"}], + couch_key_tree:find_missing( + Stemmed2, + [{0,"1"}, {1,"1a"}, {100, "x"}] + ), + "Look for missing keys." + ), + + ok. diff --git a/test/etap/062-kt-remove-leaves.t b/test/etap/062-kt-remove-leaves.t new file mode 100644 index 00000000..0d27611b --- /dev/null +++ b/test/etap/062-kt-remove-leaves.t @@ -0,0 +1,57 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +main(_) -> + code:add_pathz("src/couchdb"), + etap:plan(unknown), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + OneChild = [{0, {"1","foo",[{"1a", "bar", []}]}}], + TwoChildSibs = [{0, {"1","foo", [{"1a", "bar", []}, {"1b", "bar", []}]}}], + Stemmed = [{1, {"1a", "bar", [{"1aa", "bar", []}]}}], + + etap:is( + {TwoChildSibs, []}, + couch_key_tree:remove_leafs(TwoChildSibs, []), + "Removing no leaves has no effect on the tree." + ), + + etap:is( + {TwoChildSibs, []}, + couch_key_tree:remove_leafs(TwoChildSibs, [{0, "1"}]), + "Removing a non-existant branch has no effect." + ), + + etap:is( + {OneChild, [{1, "1b"}]}, + couch_key_tree:remove_leafs(TwoChildSibs, [{1, "1b"}]), + "Removing a leaf removes the leaf." + ), + + etap:is( + {[], [{1, "1b"},{1, "1a"}]}, + couch_key_tree:remove_leafs(TwoChildSibs, [{1, "1a"}, {1, "1b"}]), + "Removing all leaves returns an empty tree." + ), + + etap:is( + {Stemmed, []}, + couch_key_tree:remove_leafs(Stemmed, [{1, "1a"}]), + "Removing a non-existant node has no effect." + ), + + etap:is( + {[], [{2, "1aa"}]}, + couch_key_tree:remove_leafs(Stemmed, [{2, "1aa"}]), + "Removing the last leaf returns an empty tree." + ), + + ok. diff --git a/test/etap/063-kt-get-leaves.t b/test/etap/063-kt-get-leaves.t new file mode 100644 index 00000000..09c6deba --- /dev/null +++ b/test/etap/063-kt-get-leaves.t @@ -0,0 +1,86 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +main(_) -> + code:add_pathz("src/couchdb"), + etap:plan(unknown), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + TwoChildSibs = [{0, {"1","foo", [{"1a", "bar", []}, {"1b", "bar", []}]}}], + Stemmed = [{1, {"1a", "bar", [{"1aa", "bar", []}]}}], + + etap:is( + {[{"foo", {0, ["1"]}}],[]}, + couch_key_tree:get(TwoChildSibs, [{0, "1"}]), + "extract a subtree." + ), + + etap:is( + {[{"bar", {1, ["1a", "1"]}}],[]}, + couch_key_tree:get(TwoChildSibs, [{1, "1a"}]), + "extract a subtree." + ), + + etap:is( + {[],[{0,"x"}]}, + couch_key_tree:get_key_leafs(TwoChildSibs, [{0, "x"}]), + "gather up the leaves." + ), + + etap:is( + {[{"bar", {1, ["1a","1"]}}],[]}, + couch_key_tree:get_key_leafs(TwoChildSibs, [{1, "1a"}]), + "gather up the leaves." + ), + + etap:is( + {[{"bar", {1, ["1a","1"]}},{"bar",{1, ["1b","1"]}}],[]}, + couch_key_tree:get_key_leafs(TwoChildSibs, [{0, "1"}]), + "gather up the leaves." + ), + + etap:is( + {[{0,[{"1", "foo"}]}],[]}, + couch_key_tree:get_full_key_paths(TwoChildSibs, [{0, "1"}]), + "retrieve full key paths." + ), + + etap:is( + {[{1,[{"1a", "bar"},{"1", "foo"}]}],[]}, + couch_key_tree:get_full_key_paths(TwoChildSibs, [{1, "1a"}]), + "retrieve full key paths." + ), + + etap:is( + [{2, [{"1aa", "bar"},{"1a", "bar"}]}], + couch_key_tree:get_all_leafs_full(Stemmed), + "retrieve all leaves." + ), + + etap:is( + [{1, [{"1a", "bar"},{"1", "foo"}]}, {1, [{"1b", "bar"},{"1", "foo"}]}], + couch_key_tree:get_all_leafs_full(TwoChildSibs), + "retrieve all the leaves." + ), + + etap:is( + [{"bar", {2, ["1aa","1a"]}}], + couch_key_tree:get_all_leafs(Stemmed), + "retrieve all leaves." + ), + + etap:is( + [{"bar", {1, ["1a", "1"]}}, {"bar", {1, ["1b","1"]}}], + couch_key_tree:get_all_leafs(TwoChildSibs), + "retrieve all the leaves." + ), + + ok. diff --git a/test/etap/064-kt-counting.t b/test/etap/064-kt-counting.t new file mode 100644 index 00000000..03719279 --- /dev/null +++ b/test/etap/064-kt-counting.t @@ -0,0 +1,34 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +main(_) -> + code:add_pathz("src/couchdb"), + etap:plan(unknown), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + EmptyTree = [], + One = [{0, {"1","foo",[]}}], + TwoChildSibs = [{0, {"1","foo", [{"1a", "bar", []}, {"1b", "bar", []}]}}], + Stemmed = [{2, {"1bb", "boo", []}}], + + etap:is(0, couch_key_tree:count_leafs(EmptyTree), + "Empty trees have no leaves."), + + etap:is(1, couch_key_tree:count_leafs(One), + "Single node trees have a single leaf."), + + etap:is(2, couch_key_tree:count_leafs(TwoChildSibs), + "Two children siblings counted as two leaves."), + + etap:is(1, couch_key_tree:count_leafs(Stemmed), + "Stemming does not affect leaf counting."), + + ok. diff --git a/test/etap/065-kt-stemming.t b/test/etap/065-kt-stemming.t new file mode 100644 index 00000000..7ad29347 --- /dev/null +++ b/test/etap/065-kt-stemming.t @@ -0,0 +1,30 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +main(_) -> + code:add_pathz("src/couchdb"), + etap:plan(unknown), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + TwoChild = [{0, {"1","foo", [{"1a", "bar", [{"1aa", "bar", []}]}]}}], + Stemmed1 = [{1, {"1a", "bar", [{"1aa", "bar", []}]}}], + Stemmed2 = [{2, {"1aa", "bar", []}}], + + etap:is(TwoChild, couch_key_tree:stem(TwoChild, 3), + "Stemming more levels than what exists does nothing."), + + etap:is(Stemmed1, couch_key_tree:stem(TwoChild, 2), + "Stemming with a depth of two returns the deepest two nodes."), + + etap:is(Stemmed2, couch_key_tree:stem(TwoChild, 1), + "Stemming to a depth of one returns the deepest node."), + + ok. diff --git a/test/etap/070-couch-db.t b/test/etap/070-couch-db.t new file mode 100644 index 00000000..886d6500 --- /dev/null +++ b/test/etap/070-couch-db.t @@ -0,0 +1,63 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +main(_) -> + code:add_pathz("src/couchdb"), + code:add_pathz("src/mochiweb"), + + etap:plan(unknown), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + + couch_server:start( + ["etc/couchdb/default_dev.ini", "etc/couchdb/local_dev.ini"] + ), + + couch_db:create(<<"etap-test-db">>, []), + {ok, AllDbs} = couch_server:all_databases(), + etap:ok(lists:member(<<"etap-test-db">>, AllDbs), "Database was created."), + + couch_server:delete(<<"etap-test-db">>, []), + {ok, AllDbs2} = couch_server:all_databases(), + etap:ok(not lists:member(<<"etap-test-db">>, AllDbs2), + "Database was deleted."), + + MkDbName = fun(Int) -> list_to_binary("lru-" ++ integer_to_list(Int)) end, + + lists:foreach(fun(Int) -> + {ok, TestDbs} = couch_server:all_databases(), + ok = case lists:member(MkDbName(Int), TestDbs) of + true -> couch_server:delete(MkDbName(Int), []); + _ -> ok + end, + {ok, Db} = couch_db:create(MkDbName(Int), []), + ok = couch_db:close(Db) + end, lists:seq(1, 200)), + + {ok, AllDbs3} = couch_server:all_databases(), + NumCreated = lists:foldl(fun(Int, Acc) -> + true = lists:member(MkDbName(Int), AllDbs3), + Acc+1 + end, 0, lists:seq(1, 200)), + etap:is(200, NumCreated, "Created all databases."), + + lists:foreach(fun(Int) -> + ok = couch_server:delete(MkDbName(Int), []) + end, lists:seq(1, 200)), + + {ok, AllDbs4} = couch_server:all_databases(), + NumDeleted = lists:foldl(fun(Int, Acc) -> + false = lists:member(MkDbName(Int), AllDbs4), + Acc+1 + end, 0, lists:seq(1, 200)), + etap:is(200, NumDeleted, "Deleted all databases."), + + ok. -- cgit v1.2.3