diff options
author | Garren Smith <garren.smith@gmail.com> | 2020-01-29 16:48:33 +0200 |
---|---|---|
committer | Garren Smith <garren.smith@gmail.com> | 2020-01-29 16:48:33 +0200 |
commit | 5f3a7b720f4fd6458f7a58aa7c96691715e7eee8 (patch) | |
tree | 63fac39dd95d3b65e775dd410a38efa677410dc4 | |
parent | 2c277d974dc5c660f22e5ae5fa04168ae8ac2f27 (diff) | |
download | couchdb-5f3a7b720f4fd6458f7a58aa7c96691715e7eee8.tar.gz |
range query fixes from tests
-rw-r--r-- | src/mango/src/mango_cursor_view.erl | 3 | ||||
-rw-r--r-- | src/mango/src/mango_fdb.erl | 21 | ||||
-rw-r--r-- | src/mango/src/mango_idx.erl | 1 | ||||
-rw-r--r-- | src/mango/src/mango_indexer.erl | 28 | ||||
-rw-r--r-- | src/mango/test/01-index-crud-test.py | 710 | ||||
-rw-r--r-- | src/mango/test/03-operator-test.py | 4 | ||||
-rw-r--r-- | src/mango/test/05-index-selection-test.py | 1 | ||||
-rw-r--r-- | src/mango/test/11-ignore-design-docs-test.py | 2 | ||||
-rw-r--r-- | src/mango/test/13-stable-update-test.py | 2 | ||||
-rw-r--r-- | src/mango/test/21-fdb-indexing.py | 48 | ||||
-rw-r--r-- | src/mango/test/exunit/mango_indexer_test.exs | 39 | ||||
-rw-r--r-- | src/mango/test/mango.py | 4 |
12 files changed, 448 insertions, 415 deletions
diff --git a/src/mango/src/mango_cursor_view.erl b/src/mango/src/mango_cursor_view.erl index 26c60b7e3..9669b5f73 100644 --- a/src/mango/src/mango_cursor_view.erl +++ b/src/mango/src/mango_cursor_view.erl @@ -44,7 +44,8 @@ create(Db, Indexes, Selector, Opts) -> Limit = couch_util:get_value(limit, Opts, mango_opts:default_limit()), Skip = couch_util:get_value(skip, Opts, 0), Fields = couch_util:get_value(fields, Opts, all_fields), - Bookmark = couch_util:get_value(bookmark, Opts), + Bookmark = couch_util:get_value(bookmark, Opts), + io:format("Index selected ~p Range ~p ~n", [Index, IndexRanges]), {ok, #cursor{ db = Db, diff --git a/src/mango/src/mango_fdb.erl b/src/mango/src/mango_fdb.erl index 091d5f7c1..dbd22fa32 100644 --- a/src/mango/src/mango_fdb.erl +++ b/src/mango/src/mango_fdb.erl @@ -103,25 +103,12 @@ args_to_fdb_opts(Args) -> {<<255>>, _, _} -> %% all_docs no endkey []; - {[<<255>>], _, _} -> + {[], _, _} -> %% mango index no endkey []; -%% {undefined, _, _} -> -%% []; -%% {EndKey1, <<>>, rev} when not InclusiveEnd -> -%% % When we iterate in reverse with -%% % inclusive_end=false we have to set the -%% % EndKeyDocId to <<255>> so that we don't -%% % include matching rows. -%% [{end_key_gt, {EndKey1, <<255>>}}]; -%% {EndKey1, <<255>>, _} when not InclusiveEnd -> -%% % When inclusive_end=false we need to -%% % elide the default end_key_docid so as -%% % to not sort past the docids with the -%% % given end key. -%% [{end_key_gt, {EndKey1}}]; -%% {EndKey1, EndKeyDocId, _} when not InclusiveEnd -> -%% [{end_key_gt, {EndKey1, EndKeyDocId}}]; + {[<<255>>], _, _} -> + %% mango index no endkey with a $lt in selector + []; {EndKey0, EndKeyDocId, _} when InclusiveEnd -> EndKey1 = couch_views_encoding:encode(EndKey0, key), [{EndKeyName, {EndKey1, EndKeyDocId}}] diff --git a/src/mango/src/mango_idx.erl b/src/mango/src/mango_idx.erl index 57262f963..3a579dca0 100644 --- a/src/mango/src/mango_idx.erl +++ b/src/mango/src/mango_idx.erl @@ -76,6 +76,7 @@ ddoc_fold_cb({row, Row}, Acc) -> rows := Rows } = Acc, {_, Id} = lists:keyfind(id, 1, Row), + io:format("VIEW ~p ~n", [Row]), {ok, Doc} = fabric2_db:open_doc(Db, Id), JSONDoc = couch_doc:to_json_obj(Doc, []), {Props} = JSONDoc, diff --git a/src/mango/src/mango_indexer.erl b/src/mango/src/mango_indexer.erl index 36eb2d3b7..20af5bd58 100644 --- a/src/mango/src/mango_indexer.erl +++ b/src/mango/src/mango_indexer.erl @@ -26,6 +26,7 @@ % Todo: Check if design doc is mango index and kick off background worker % to build new index update(Db, Change, #doc{id = <<?DESIGN_DOC_PREFIX, _/binary>>} = Doc, OldDoc) -> + io:format("DESIGN DOC SAVED ~p ~n", [Doc]), ok; update(Db, deleted, _, OldDoc) -> @@ -35,15 +36,23 @@ update(Db, updated, Doc, OldDoc) -> ok; update(Db, created, Doc, _) -> - #doc{id = DocId} = Doc, - Indexes = mango_idx:list(Db), - Indexes1 = filter_json_indexes(Indexes), - io:format("UPDATE INDEXES ~p ~n filtered ~p ~n", [Indexes, Indexes1]), - JSONDoc = mango_json:to_binary(couch_doc:to_json_obj(Doc, [])), - io:format("DOC ~p ~n", [Doc]), - Results = index_doc(Indexes1, JSONDoc), - io:format("Update ~p ~n, ~p ~n Results ~p ~n", [Doc, JSONDoc, Results]), - mango_fdb:write_doc(Db, DocId, Results). + try + io:format("CREATED ~p ~n", [Doc]), + #doc{id = DocId} = Doc, + Indexes = mango_idx:list(Db), + Indexes1 = filter_json_indexes(Indexes), + io:format("UPDATE INDEXES ~p ~n filtered ~p ~n", [Indexes, Indexes1]), + JSONDoc = mango_json:to_binary(couch_doc:to_json_obj(Doc, [])), + io:format("DOC ~p ~n", [Doc]), + Results = index_doc(Indexes1, JSONDoc), + io:format("Update ~p ~n, ~p ~n Results ~p ~n", [Doc, JSONDoc, Results]), + mango_fdb:write_doc(Db, DocId, Results) + catch + Error:Reason -> + io:format("ERROR ~p ~p ~p ~n", [Error, Reason, erlang:display(erlang:get_stacktrace())]), + ok + end, + ok. filter_json_indexes(Indexes) -> @@ -54,7 +63,6 @@ filter_json_indexes(Indexes) -> index_doc(Indexes, Doc) -> lists:foldl(fun(Idx, Acc) -> - io:format("II ~p ~n", [Idx]), {IdxDef} = mango_idx:def(Idx), Results = get_index_entries(IdxDef, Doc), case lists:member(not_found, Results) of diff --git a/src/mango/test/01-index-crud-test.py b/src/mango/test/01-index-crud-test.py index 6e0208a07..dd9ab1ade 100644 --- a/src/mango/test/01-index-crud-test.py +++ b/src/mango/test/01-index-crud-test.py @@ -26,63 +26,63 @@ class IndexCrudTests(mango.DbPerClass): def setUp(self): self.db.recreate() - # def test_bad_fields(self): - # bad_fields = [ - # None, - # True, - # False, - # "bing", - # 2.0, - # {"foo": "bar"}, - # [{"foo": 2}], - # [{"foo": "asc", "bar": "desc"}], - # [{"foo": "asc"}, {"bar": "desc"}], - # [""], - # ] - # for fields in bad_fields: - # try: - # self.db.create_index(fields) - # except Exception as e: - # self.assertEqual(e.response.status_code, 400) - # else: - # raise AssertionError("bad create index") - # - # def test_bad_types(self): - # bad_types = [ - # None, - # True, - # False, - # 1.5, - # "foo", # Future support - # "geo", # Future support - # {"foo": "bar"}, - # ["baz", 3.0], - # ] - # for bt in bad_types: - # try: - # self.db.create_index(["foo"], idx_type=bt) - # except Exception as e: - # self.assertEqual( - # e.response.status_code, 400, (bt, e.response.status_code) - # ) - # else: - # raise AssertionError("bad create index") - # - # def test_bad_names(self): - # bad_names = [True, False, 1.5, {"foo": "bar"}, [None, False]] - # for bn in bad_names: - # try: - # self.db.create_index(["foo"], name=bn) - # except Exception as e: - # self.assertEqual(e.response.status_code, 400) - # else: - # raise AssertionError("bad create index") - # try: - # self.db.create_index(["foo"], ddoc=bn) - # except Exception as e: - # self.assertEqual(e.response.status_code, 400) - # else: - # raise AssertionError("bad create index") + def test_bad_fields(self): + bad_fields = [ + None, + True, + False, + "bing", + 2.0, + {"foo": "bar"}, + [{"foo": 2}], + [{"foo": "asc", "bar": "desc"}], + [{"foo": "asc"}, {"bar": "desc"}], + [""], + ] + for fields in bad_fields: + try: + self.db.create_index(fields) + except Exception as e: + self.assertEqual(e.response.status_code, 400) + else: + raise AssertionError("bad create index") + + def test_bad_types(self): + bad_types = [ + None, + True, + False, + 1.5, + "foo", # Future support + "geo", # Future support + {"foo": "bar"}, + ["baz", 3.0], + ] + for bt in bad_types: + try: + self.db.create_index(["foo"], idx_type=bt) + except Exception as e: + self.assertEqual( + e.response.status_code, 400, (bt, e.response.status_code) + ) + else: + raise AssertionError("bad create index") + + def test_bad_names(self): + bad_names = [True, False, 1.5, {"foo": "bar"}, [None, False]] + for bn in bad_names: + try: + self.db.create_index(["foo"], name=bn) + except Exception as e: + self.assertEqual(e.response.status_code, 400) + else: + raise AssertionError("bad create index") + try: + self.db.create_index(["foo"], ddoc=bn) + except Exception as e: + self.assertEqual(e.response.status_code, 400) + else: + raise AssertionError("bad create index") def test_create_idx_01(self): fields = ["foo", "bar"] @@ -95,301 +95,301 @@ class IndexCrudTests(mango.DbPerClass): return raise AssertionError("index not created") -# def test_create_idx_01_exists(self): -# fields = ["foo", "bar"] -# ret = self.db.create_index(fields, name="idx_01") -# assert ret is True -# ret = self.db.create_index(fields, name="idx_01") -# assert ret is False -# -# def test_create_idx_02(self): -# fields = ["baz", "foo"] -# ret = self.db.create_index(fields, name="idx_02") -# assert ret is True -# for idx in self.db.list_indexes(): -# if idx["name"] != "idx_02": -# continue -# self.assertEqual(idx["def"]["fields"], [{"baz": "asc"}, {"foo": "asc"}]) -# return -# raise AssertionError("index not created") -# -# def test_ignore_design_docs(self): -# fields = ["baz", "foo"] -# ret = self.db.create_index(fields, name="idx_02") -# assert ret is True -# self.db.save_doc({ -# "_id": "_design/ignore", -# "views": { -# "view1": { -# "map": "function (doc) { emit(doc._id, 1)}" -# } -# } -# }) -# Indexes = self.db.list_indexes() -# self.assertEqual(len(Indexes), 2) -# -# def test_read_idx_doc(self): -# self.db.create_index(["foo", "bar"], name="idx_01") -# self.db.create_index(["hello", "bar"]) -# for idx in self.db.list_indexes(): -# if idx["type"] == "special": -# continue -# ddocid = idx["ddoc"] -# doc = self.db.open_doc(ddocid) -# self.assertEqual(doc["_id"], ddocid) -# info = self.db.ddoc_info(ddocid) -# self.assertEqual(info["name"], ddocid.split("_design/")[-1]) -# -# def test_delete_idx_escaped(self): -# self.db.create_index(["foo", "bar"], name="idx_01") -# pre_indexes = self.db.list_indexes() -# ret = self.db.create_index(["bing"], name="idx_del_1") -# assert ret is True -# for idx in self.db.list_indexes(): -# if idx["name"] != "idx_del_1": -# continue -# self.assertEqual(idx["def"]["fields"], [{"bing": "asc"}]) -# self.db.delete_index(idx["ddoc"].replace("/", "%2F"), idx["name"]) -# post_indexes = self.db.list_indexes() -# self.assertEqual(pre_indexes, post_indexes) -# -# def test_delete_idx_unescaped(self): -# pre_indexes = self.db.list_indexes() -# ret = self.db.create_index(["bing"], name="idx_del_2") -# assert ret is True -# for idx in self.db.list_indexes(): -# if idx["name"] != "idx_del_2": -# continue -# self.assertEqual(idx["def"]["fields"], [{"bing": "asc"}]) -# self.db.delete_index(idx["ddoc"], idx["name"]) -# post_indexes = self.db.list_indexes() -# self.assertEqual(pre_indexes, post_indexes) -# -# def test_delete_idx_no_design(self): -# pre_indexes = self.db.list_indexes() -# ret = self.db.create_index(["bing"], name="idx_del_3") -# assert ret is True -# for idx in self.db.list_indexes(): -# if idx["name"] != "idx_del_3": -# continue -# self.assertEqual(idx["def"]["fields"], [{"bing": "asc"}]) -# self.db.delete_index(idx["ddoc"].split("/")[-1], idx["name"]) -# post_indexes = self.db.list_indexes() -# self.assertEqual(pre_indexes, post_indexes) -# -# def test_bulk_delete(self): -# fields = ["field1"] -# ret = self.db.create_index(fields, name="idx_01") -# assert ret is True -# -# fields = ["field2"] -# ret = self.db.create_index(fields, name="idx_02") -# assert ret is True -# -# fields = ["field3"] -# ret = self.db.create_index(fields, name="idx_03") -# assert ret is True -# -# docids = [] -# -# for idx in self.db.list_indexes(): -# if idx["ddoc"] is not None: -# docids.append(idx["ddoc"]) -# -# docids.append("_design/this_is_not_an_index_name") -# -# ret = self.db.bulk_delete(docids) -# -# self.assertEqual(ret["fail"][0]["id"], "_design/this_is_not_an_index_name") -# self.assertEqual(len(ret["success"]), 3) -# -# for idx in self.db.list_indexes(): -# assert idx["type"] != "json" -# assert idx["type"] != "text" -# -# def test_recreate_index(self): -# pre_indexes = self.db.list_indexes() -# for i in range(5): -# ret = self.db.create_index(["bing"], name="idx_recreate") -# assert ret is True -# for idx in self.db.list_indexes(): -# if idx["name"] != "idx_recreate": -# continue -# self.assertEqual(idx["def"]["fields"], [{"bing": "asc"}]) -# self.db.delete_index(idx["ddoc"], idx["name"]) -# break -# post_indexes = self.db.list_indexes() -# self.assertEqual(pre_indexes, post_indexes) -# -# def test_delete_missing(self): -# # Missing design doc -# try: -# self.db.delete_index("this_is_not_a_design_doc_id", "foo") -# except Exception as e: -# self.assertEqual(e.response.status_code, 404) -# else: -# raise AssertionError("bad index delete") -# -# # Missing view name -# ret = self.db.create_index(["fields"], name="idx_01") -# indexes = self.db.list_indexes() -# not_special = [idx for idx in indexes if idx["type"] != "special"] -# idx = random.choice(not_special) -# ddocid = idx["ddoc"].split("/")[-1] -# try: -# self.db.delete_index(ddocid, "this_is_not_an_index_name") -# except Exception as e: -# self.assertEqual(e.response.status_code, 404) -# else: -# raise AssertionError("bad index delete") -# -# # Bad view type -# try: -# self.db.delete_index(ddocid, idx["name"], idx_type="not_a_real_type") -# except Exception as e: -# self.assertEqual(e.response.status_code, 404) -# else: -# raise AssertionError("bad index delete") -# -# def test_limit_skip_index(self): -# fields = ["field1"] -# ret = self.db.create_index(fields, name="idx_01") -# assert ret is True -# -# fields = ["field2"] -# ret = self.db.create_index(fields, name="idx_02") -# assert ret is True -# -# fields = ["field3"] -# ret = self.db.create_index(fields, name="idx_03") -# assert ret is True -# -# fields = ["field4"] -# ret = self.db.create_index(fields, name="idx_04") -# assert ret is True -# -# fields = ["field5"] -# ret = self.db.create_index(fields, name="idx_05") -# assert ret is True -# -# self.assertEqual(len(self.db.list_indexes(limit=2)), 2) -# self.assertEqual(len(self.db.list_indexes(limit=5, skip=4)), 2) -# self.assertEqual(len(self.db.list_indexes(skip=5)), 1) -# self.assertEqual(len(self.db.list_indexes(skip=6)), 0) -# self.assertEqual(len(self.db.list_indexes(skip=100)), 0) -# self.assertEqual(len(self.db.list_indexes(limit=10000000)), 6) -# -# try: -# self.db.list_indexes(skip=-1) -# except Exception as e: -# self.assertEqual(e.response.status_code, 500) -# -# try: -# self.db.list_indexes(limit=0) -# except Exception as e: -# self.assertEqual(e.response.status_code, 500) -# -# def test_out_of_sync(self): -# self.db.save_docs(copy.deepcopy(DOCS)) -# self.db.create_index(["age"], name="age") -# -# selector = {"age": {"$gt": 0}} -# docs = self.db.find( -# selector, use_index="_design/a017b603a47036005de93034ff689bbbb6a873c4" -# ) -# self.assertEqual(len(docs), 2) -# -# self.db.delete_doc("1") -# -# docs1 = self.db.find( -# selector, -# update="False", -# use_index="_design/a017b603a47036005de93034ff689bbbb6a873c4", -# ) -# self.assertEqual(len(docs1), 1) -# -# -# @unittest.skipUnless(mango.has_text_service(), "requires text service") -# class IndexCrudTextTests(mango.DbPerClass): -# def setUp(self): -# self.db.recreate() -# -# def test_create_text_idx(self): -# fields = [ -# {"name": "stringidx", "type": "string"}, -# {"name": "booleanidx", "type": "boolean"}, -# ] -# ret = self.db.create_text_index(fields=fields, name="text_idx_01") -# assert ret is True -# for idx in self.db.list_indexes(): -# if idx["name"] != "text_idx_01": -# continue -# self.assertEqual( -# idx["def"]["fields"], -# [{"stringidx": "string"}, {"booleanidx": "boolean"}], -# ) -# return -# raise AssertionError("index not created") -# -# def test_create_bad_text_idx(self): -# bad_fields = [ -# True, -# False, -# "bing", -# 2.0, -# ["foo", "bar"], -# [{"name": "foo2"}], -# [{"name": "foo3", "type": "garbage"}], -# [{"type": "number"}], -# [{"name": "age", "type": "number"}, {"name": "bad"}], -# [{"name": "age", "type": "number"}, "bla"], -# [{"name": "", "type": "number"}, "bla"], -# ] -# for fields in bad_fields: -# try: -# self.db.create_text_index(fields=fields) -# except Exception as e: -# self.assertEqual(e.response.status_code, 400) -# else: -# raise AssertionError("bad create text index") -# -# def test_limit_skip_index(self): -# fields = ["field1"] -# ret = self.db.create_index(fields, name="idx_01") -# assert ret is True -# -# fields = ["field2"] -# ret = self.db.create_index(fields, name="idx_02") -# assert ret is True -# -# fields = ["field3"] -# ret = self.db.create_index(fields, name="idx_03") -# assert ret is True -# -# fields = ["field4"] -# ret = self.db.create_index(fields, name="idx_04") -# assert ret is True -# -# fields = [ -# {"name": "stringidx", "type": "string"}, -# {"name": "booleanidx", "type": "boolean"}, -# ] -# ret = self.db.create_text_index(fields=fields, name="idx_05") -# assert ret is True -# -# self.assertEqual(len(self.db.list_indexes(limit=2)), 2) -# self.assertEqual(len(self.db.list_indexes(limit=5, skip=4)), 2) -# self.assertEqual(len(self.db.list_indexes(skip=5)), 1) -# self.assertEqual(len(self.db.list_indexes(skip=6)), 0) -# self.assertEqual(len(self.db.list_indexes(skip=100)), 0) -# self.assertEqual(len(self.db.list_indexes(limit=10000000)), 6) -# -# try: -# self.db.list_indexes(skip=-1) -# except Exception as e: -# self.assertEqual(e.response.status_code, 500) -# -# try: -# self.db.list_indexes(limit=0) -# except Exception as e: -# self.assertEqual(e.response.status_code, 500) + def test_create_idx_01_exists(self): + fields = ["foo", "bar"] + ret = self.db.create_index(fields, name="idx_01") + assert ret is True + ret = self.db.create_index(fields, name="idx_01") + assert ret is False + + def test_create_idx_02(self): + fields = ["baz", "foo"] + ret = self.db.create_index(fields, name="idx_02") + assert ret is True + for idx in self.db.list_indexes(): + if idx["name"] != "idx_02": + continue + self.assertEqual(idx["def"]["fields"], [{"baz": "asc"}, {"foo": "asc"}]) + return + raise AssertionError("index not created") + + def test_ignore_design_docs(self): + fields = ["baz", "foo"] + ret = self.db.create_index(fields, name="idx_02") + assert ret is True + self.db.save_doc({ + "_id": "_design/ignore", + "views": { + "view1": { + "map": "function (doc) { emit(doc._id, 1)}" + } + } + }) + Indexes = self.db.list_indexes() + self.assertEqual(len(Indexes), 2) + + def test_read_idx_doc(self): + self.db.create_index(["foo", "bar"], name="idx_01") + self.db.create_index(["hello", "bar"]) + for idx in self.db.list_indexes(): + if idx["type"] == "special": + continue + ddocid = idx["ddoc"] + doc = self.db.open_doc(ddocid) + self.assertEqual(doc["_id"], ddocid) + info = self.db.ddoc_info(ddocid) + self.assertEqual(info["name"], ddocid.split("_design/")[-1]) + + def test_delete_idx_escaped(self): + self.db.create_index(["foo", "bar"], name="idx_01") + pre_indexes = self.db.list_indexes() + ret = self.db.create_index(["bing"], name="idx_del_1") + assert ret is True + for idx in self.db.list_indexes(): + if idx["name"] != "idx_del_1": + continue + self.assertEqual(idx["def"]["fields"], [{"bing": "asc"}]) + self.db.delete_index(idx["ddoc"].replace("/", "%2F"), idx["name"]) + post_indexes = self.db.list_indexes() + self.assertEqual(pre_indexes, post_indexes) + + def test_delete_idx_unescaped(self): + pre_indexes = self.db.list_indexes() + ret = self.db.create_index(["bing"], name="idx_del_2") + assert ret is True + for idx in self.db.list_indexes(): + if idx["name"] != "idx_del_2": + continue + self.assertEqual(idx["def"]["fields"], [{"bing": "asc"}]) + self.db.delete_index(idx["ddoc"], idx["name"]) + post_indexes = self.db.list_indexes() + self.assertEqual(pre_indexes, post_indexes) + + def test_delete_idx_no_design(self): + pre_indexes = self.db.list_indexes() + ret = self.db.create_index(["bing"], name="idx_del_3") + assert ret is True + for idx in self.db.list_indexes(): + if idx["name"] != "idx_del_3": + continue + self.assertEqual(idx["def"]["fields"], [{"bing": "asc"}]) + self.db.delete_index(idx["ddoc"].split("/")[-1], idx["name"]) + post_indexes = self.db.list_indexes() + self.assertEqual(pre_indexes, post_indexes) + + def test_bulk_delete(self): + fields = ["field1"] + ret = self.db.create_index(fields, name="idx_01") + assert ret is True + + fields = ["field2"] + ret = self.db.create_index(fields, name="idx_02") + assert ret is True + + fields = ["field3"] + ret = self.db.create_index(fields, name="idx_03") + assert ret is True + + docids = [] + + for idx in self.db.list_indexes(): + if idx["ddoc"] is not None: + docids.append(idx["ddoc"]) + + docids.append("_design/this_is_not_an_index_name") + + ret = self.db.bulk_delete(docids) + + self.assertEqual(ret["fail"][0]["id"], "_design/this_is_not_an_index_name") + self.assertEqual(len(ret["success"]), 3) + + for idx in self.db.list_indexes(): + assert idx["type"] != "json" + assert idx["type"] != "text" + + def test_recreate_index(self): + pre_indexes = self.db.list_indexes() + for i in range(5): + ret = self.db.create_index(["bing"], name="idx_recreate") + assert ret is True + for idx in self.db.list_indexes(): + if idx["name"] != "idx_recreate": + continue + self.assertEqual(idx["def"]["fields"], [{"bing": "asc"}]) + self.db.delete_index(idx["ddoc"], idx["name"]) + break + post_indexes = self.db.list_indexes() + self.assertEqual(pre_indexes, post_indexes) + + def test_delete_missing(self): + # Missing design doc + try: + self.db.delete_index("this_is_not_a_design_doc_id", "foo") + except Exception as e: + self.assertEqual(e.response.status_code, 404) + else: + raise AssertionError("bad index delete") + + # Missing view name + ret = self.db.create_index(["fields"], name="idx_01") + indexes = self.db.list_indexes() + not_special = [idx for idx in indexes if idx["type"] != "special"] + idx = random.choice(not_special) + ddocid = idx["ddoc"].split("/")[-1] + try: + self.db.delete_index(ddocid, "this_is_not_an_index_name") + except Exception as e: + self.assertEqual(e.response.status_code, 404) + else: + raise AssertionError("bad index delete") + + # Bad view type + try: + self.db.delete_index(ddocid, idx["name"], idx_type="not_a_real_type") + except Exception as e: + self.assertEqual(e.response.status_code, 404) + else: + raise AssertionError("bad index delete") + + def test_limit_skip_index(self): + fields = ["field1"] + ret = self.db.create_index(fields, name="idx_01") + assert ret is True + + fields = ["field2"] + ret = self.db.create_index(fields, name="idx_02") + assert ret is True + + fields = ["field3"] + ret = self.db.create_index(fields, name="idx_03") + assert ret is True + + fields = ["field4"] + ret = self.db.create_index(fields, name="idx_04") + assert ret is True + + fields = ["field5"] + ret = self.db.create_index(fields, name="idx_05") + assert ret is True + + self.assertEqual(len(self.db.list_indexes(limit=2)), 2) + self.assertEqual(len(self.db.list_indexes(limit=5, skip=4)), 2) + self.assertEqual(len(self.db.list_indexes(skip=5)), 1) + self.assertEqual(len(self.db.list_indexes(skip=6)), 0) + self.assertEqual(len(self.db.list_indexes(skip=100)), 0) + self.assertEqual(len(self.db.list_indexes(limit=10000000)), 6) + + try: + self.db.list_indexes(skip=-1) + except Exception as e: + self.assertEqual(e.response.status_code, 500) + + try: + self.db.list_indexes(limit=0) + except Exception as e: + self.assertEqual(e.response.status_code, 500) + + def test_out_of_sync(self): + self.db.save_docs(copy.deepcopy(DOCS)) + self.db.create_index(["age"], name="age") + + selector = {"age": {"$gt": 0}} + docs = self.db.find( + selector, use_index="_design/a017b603a47036005de93034ff689bbbb6a873c4" + ) + self.assertEqual(len(docs), 2) + + self.db.delete_doc("1") + + docs1 = self.db.find( + selector, + update="False", + use_index="_design/a017b603a47036005de93034ff689bbbb6a873c4", + ) + self.assertEqual(len(docs1), 1) + + +@unittest.skipUnless(mango.has_text_service(), "requires text service") +class IndexCrudTextTests(mango.DbPerClass): + def setUp(self): + self.db.recreate() + + def test_create_text_idx(self): + fields = [ + {"name": "stringidx", "type": "string"}, + {"name": "booleanidx", "type": "boolean"}, + ] + ret = self.db.create_text_index(fields=fields, name="text_idx_01") + assert ret is True + for idx in self.db.list_indexes(): + if idx["name"] != "text_idx_01": + continue + self.assertEqual( + idx["def"]["fields"], + [{"stringidx": "string"}, {"booleanidx": "boolean"}], + ) + return + raise AssertionError("index not created") + + def test_create_bad_text_idx(self): + bad_fields = [ + True, + False, + "bing", + 2.0, + ["foo", "bar"], + [{"name": "foo2"}], + [{"name": "foo3", "type": "garbage"}], + [{"type": "number"}], + [{"name": "age", "type": "number"}, {"name": "bad"}], + [{"name": "age", "type": "number"}, "bla"], + [{"name": "", "type": "number"}, "bla"], + ] + for fields in bad_fields: + try: + self.db.create_text_index(fields=fields) + except Exception as e: + self.assertEqual(e.response.status_code, 400) + else: + raise AssertionError("bad create text index") + + def test_limit_skip_index(self): + fields = ["field1"] + ret = self.db.create_index(fields, name="idx_01") + assert ret is True + + fields = ["field2"] + ret = self.db.create_index(fields, name="idx_02") + assert ret is True + + fields = ["field3"] + ret = self.db.create_index(fields, name="idx_03") + assert ret is True + + fields = ["field4"] + ret = self.db.create_index(fields, name="idx_04") + assert ret is True + + fields = [ + {"name": "stringidx", "type": "string"}, + {"name": "booleanidx", "type": "boolean"}, + ] + ret = self.db.create_text_index(fields=fields, name="idx_05") + assert ret is True + + self.assertEqual(len(self.db.list_indexes(limit=2)), 2) + self.assertEqual(len(self.db.list_indexes(limit=5, skip=4)), 2) + self.assertEqual(len(self.db.list_indexes(skip=5)), 1) + self.assertEqual(len(self.db.list_indexes(skip=6)), 0) + self.assertEqual(len(self.db.list_indexes(skip=100)), 0) + self.assertEqual(len(self.db.list_indexes(limit=10000000)), 6) + + try: + self.db.list_indexes(skip=-1) + except Exception as e: + self.assertEqual(e.response.status_code, 500) + + try: + self.db.list_indexes(limit=0) + except Exception as e: + self.assertEqual(e.response.status_code, 500) diff --git a/src/mango/test/03-operator-test.py b/src/mango/test/03-operator-test.py index 935f470bb..fdcd079b0 100644 --- a/src/mango/test/03-operator-test.py +++ b/src/mango/test/03-operator-test.py @@ -190,5 +190,5 @@ class OperatorAllDocsTests(mango.UserDocsTestsNoIndexes, OperatorTests): doc_id = "8e1c90c0-ac18-4832-8081-40d14325bde0" r = self.db.find({"_id": doc_id}, explain=True, return_raw=True) - self.assertEqual(r["mrargs"]["end_key"], doc_id) - self.assertEqual(r["mrargs"]["start_key"], doc_id) + self.assertEqual(r["args"]["end_key"], doc_id) + self.assertEqual(r["args"]["start_key"], doc_id) diff --git a/src/mango/test/05-index-selection-test.py b/src/mango/test/05-index-selection-test.py index 3f7fb9f21..e6d74bd1c 100644 --- a/src/mango/test/05-index-selection-test.py +++ b/src/mango/test/05-index-selection-test.py @@ -183,6 +183,7 @@ class IndexSelectionTests: # This doc will not be saved given the new ddoc validation code # in couch_mrview + @unittest.skip("need to add couch_mrview:validate_ddoc_fields") def test_manual_bad_view_idx01(self): design_doc = { "_id": "_design/bad_view_index", diff --git a/src/mango/test/11-ignore-design-docs-test.py b/src/mango/test/11-ignore-design-docs-test.py index f31dcc5d1..bb8cf3ac7 100644 --- a/src/mango/test/11-ignore-design-docs-test.py +++ b/src/mango/test/11-ignore-design-docs-test.py @@ -19,6 +19,8 @@ DOCS = [ {"_id": "54af50622071121b25402dc3", "user_id": 1, "age": 11, "name": "Eddie"}, ] +# [{erlfdb_nif,erlfdb_future_get,[#Ref<0.1264327726.2786983941.139980>],[]},{erlfdb,fold_range_int,4,[{file,"src/erlfdb.erl"},{line,675}]},{fabric2_fdb,get_winning_revs_wait,2,[{file,"src/fabric2_fdb.erl"},{line,474}]},{fabric2_db,'-open_doc/3-fun-1-',5,[{file,"src/fabric2_db.erl"},{line,503}]},{mango_idx,ddoc_fold_cb,2,[{file,"src/mango_idx.erl"},{line,80}]},{fabric2_db,'-fold_docs/4-fun-0-',6,[{file,"src/fabric2_db.erl"},{line,795}]},{fabric2_fdb,fold_range_cb,2,[{file,"src/fabric2_fdb.erl"},{line,1379}]},{lists,foldl,3,[{file,"lists.erl"},{line,1263}]}] + class IgnoreDesignDocsForAllDocsIndexTests(mango.DbPerClass): def test_should_not_return_design_docs(self): diff --git a/src/mango/test/13-stable-update-test.py b/src/mango/test/13-stable-update-test.py index 348ac5ee7..1af63b98e 100644 --- a/src/mango/test/13-stable-update-test.py +++ b/src/mango/test/13-stable-update-test.py @@ -12,6 +12,7 @@ import copy import mango +import unittest DOCS1 = [ { @@ -39,6 +40,7 @@ class SupportStableAndUpdate(mango.DbPerClass): self.db.create_index(["name"]) self.db.save_docs(copy.deepcopy(DOCS1)) + @unittest.skip("this FDB doesn't support this") def test_update_updates_view_when_specified(self): docs = self.db.find({"name": "Eddie"}, update=False) assert len(docs) == 0 diff --git a/src/mango/test/21-fdb-indexing.py b/src/mango/test/21-fdb-indexing.py new file mode 100644 index 000000000..e1cfd9030 --- /dev/null +++ b/src/mango/test/21-fdb-indexing.py @@ -0,0 +1,48 @@ +# -*- coding: latin-1 -*- +# 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. + +import mango +import copy + +DOCS = [ + {"_id": "100", "name": "Jimi", "location": "AUS", "user_id": 1, "same": "value"}, + {"_id": "200", "name": "Eddie", "location": "BRA", "user_id": 2, "same": "value"}, + {"_id": "300", "name": "Harry", "location": "CAN", "user_id": 3, "same": "value"}, + {"_id": "400", "name": "Eddie", "location": "DEN", "user_id": 4, "same": "value"}, + {"_id": "500", "name": "Jones", "location": "ETH", "user_id": 5, "same": "value"} +] + +class FdbIndexingTests(mango.DbPerClass): + def setUp(self): + self.db.recreate() + self.db.create_index(["name"], name="name") + self.db.save_docs(copy.deepcopy(DOCS)) + + def test_doc_update(self): + docs = self.db.find({"name": "Eddie"}) + self.assertEqual(len(docs), 2) + self.assertEqual(docs[0]["_id"], "200") + self.assertEqual(docs[1]["_id"], "400") + + doc = self.db.open_doc("400") + doc["name"] = "NotEddie" + self.db.save_doc(doc) + + docs = self.db.find({"name": "Eddie"}) + print("DD") + print(docs) + self.assertEqual(len(docs), 1) + self.assertEqual(docs[0]["_id"], "200") + + + diff --git a/src/mango/test/exunit/mango_indexer_test.exs b/src/mango/test/exunit/mango_indexer_test.exs index 16c6e4924..f62f47ea9 100644 --- a/src/mango/test/exunit/mango_indexer_test.exs +++ b/src/mango/test/exunit/mango_indexer_test.exs @@ -26,7 +26,7 @@ defmodule MangoIndexerTest do idx_ddocs = create_indexes(db) docs = create_docs() - IO.inspect idx_ddocs + IO.inspect(idx_ddocs) {ok, _} = :fabric2_db.update_docs(db, ddocs ++ idx_ddocs) {ok, _} = :fabric2_db.update_docs(db, docs) @@ -42,7 +42,7 @@ defmodule MangoIndexerTest do } end - test "create design doc through _index", context do + test "update doc", context do db = context[:db] end @@ -59,31 +59,10 @@ defmodule MangoIndexerTest do {:ok, idx} = :mango_idx.new(db, opts) db_opts = [{:user_ctx, db["user_ctx"]}, :deleted, :ejson_body] {:ok, ddoc} = :mango_util.load_ddoc(db, :mango_idx.ddoc(idx), db_opts) - {:ok ,new_ddoc} = :mango_idx.add(ddoc, idx) + {:ok, new_ddoc} = :mango_idx.add(ddoc, idx) [new_ddoc] end - # Create 1 design doc that should be filtered out and ignored - defp create_ddocs() do - views = %{ - "_id" => "_design/bar", - "views" => %{ - "dates_sum" => %{ - "map" => """ - function(doc) { - if (doc.date) { - emit(doc.date, doc.date_val); - } - } - """ - } - } - } - - ddoc1 = :couch_doc.from_json_obj(:jiffy.decode(:jiffy.encode(views))) - [] - end - defp create_docs() do for i <- 1..1 do group = @@ -95,12 +74,12 @@ defmodule MangoIndexerTest do :couch_doc.from_json_obj( {[ - {"_id", "doc-id-#{i}"}, - {"value", i}, - {"val_str", Integer.to_string(i, 8)}, - {"some", "field"}, - {"group", group} - ]} + {"_id", "doc-id-#{i}"}, + {"value", i}, + {"val_str", Integer.to_string(i, 8)}, + {"some", "field"}, + {"group", group} + ]} ) end end diff --git a/src/mango/test/mango.py b/src/mango/test/mango.py index 5ce4219b2..a39476dec 100644 --- a/src/mango/test/mango.py +++ b/src/mango/test/mango.py @@ -110,7 +110,11 @@ class Database(object): def save_docs(self, docs, **kwargs): body = json.dumps({"docs": docs}) r = self.sess.post(self.path("_bulk_docs"), data=body, params=kwargs) + print("DOC") + print(docs) r.raise_for_status() + print("RES") + print(r.json()) for doc, result in zip(docs, r.json()): doc["_id"] = result["id"] doc["_rev"] = result["rev"] |