summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuanjo <juanjo@localhost.localdomain>2018-01-24 15:01:40 +0100
committerJan Lehnardt <jan@apache.org>2018-01-31 14:10:49 +0100
commit960a6f9dcca7ece74838e377b091050284a3233a (patch)
tree1d3781a86a224d55722c273f254a1484bb18a91d
parent884db891de6f7004f31a9a1a9d50b0162b1dca8e (diff)
downloadcouchdb-960a6f9dcca7ece74838e377b091050284a3233a.tar.gz
Fix for issue #603 - Error 500 when creating a db below quorum
Add degrade-cluster option for cluster testing Add tests for different cluster conditions with/without quorum Add test-cluster-with-quorum and test-cluster-without-quorum tasks
-rw-r--r--Makefile34
-rwxr-xr-xdev/run24
-rw-r--r--src/fabric/src/fabric_db_create.erl4
-rwxr-xr-xtest/javascript/run16
-rw-r--r--test/javascript/tests-cluster/with-quorum/db-creation.js27
-rw-r--r--test/javascript/tests-cluster/without-quorum/db-creation.js28
6 files changed, 122 insertions, 11 deletions
diff --git a/Makefile b/Makefile
index c8c0b093f..05a1f3982 100644
--- a/Makefile
+++ b/Makefile
@@ -129,6 +129,40 @@ endif
'test/javascript/run --suites "$(suites)" \
--ignore "$(ignore_js_suites)"'
+.PHONY: test-cluster-with-quorum
+test-cluster-with-quorum:
+ @mkdir -p share/www/script/test
+ifeq ($(IN_RELEASE), true)
+ @cp test/javascript/tests/lorem*.txt share/www/script/test/
+else
+ @mkdir -p src/fauxton/dist/release/test
+ @cp test/javascript/tests/lorem*.txt src/fauxton/dist/release/test/
+endif
+ @rm -rf dev/lib
+ @dev/run -n 3 -q --with-admin-party-please \
+ --enable-erlang-views --degrade-cluster 1 \
+ -c 'startup_jitter=0' \
+ 'test/javascript/run --suites "$(suites)" \
+ --ignore "$(ignore_js_suites)" \
+ --path test/javascript/tests-cluster/with-quorum'
+
+.PHONY: test-cluster-without-quorum
+test-cluster-without-quorum:
+ @mkdir -p share/www/script/test
+ifeq ($(IN_RELEASE), true)
+ @cp test/javascript/tests/lorem*.txt share/www/script/test/
+else
+ @mkdir -p src/fauxton/dist/release/test
+ @cp test/javascript/tests/lorem*.txt src/fauxton/dist/release/test/
+endif
+ @rm -rf dev/lib
+ @dev/run -n 3 -q --with-admin-party-please \
+ --enable-erlang-views --degrade-cluster 2 \
+ -c 'startup_jitter=0' \
+ 'test/javascript/run --suites "$(suites)" \
+ --ignore "$(ignore_js_suites)" \
+ --path test/javascript/tests-cluster/without-quorum'
+
.PHONY: soak-javascript
soak-javascript:
@mkdir -p share/www/script/test
diff --git a/dev/run b/dev/run
index 4924de1f6..a5d8fde8c 100755
--- a/dev/run
+++ b/dev/run
@@ -130,6 +130,8 @@ def setup_argparse():
help='The node number to seed them when creating the node(s)')
parser.add_option('-c', '--config-overrides', action="append", default=[],
help='Optional key=val config overrides. Can be repeated')
+ parser.add_option('--degrade-cluster', dest="degrade_cluster",type=int, default=0,
+ help='The number of nodes that should be stopped after cluster config')
return parser.parse_args()
@@ -142,6 +144,7 @@ def setup_context(opts, args):
'admin': opts.admin.split(':', 1) if opts.admin else None,
'nodes': ['node%d' % (i + opts.node_number) for i in range(opts.nodes)],
'node_number': opts.node_number,
+ 'degrade_cluster': opts.degrade_cluster,
'devdir': os.path.dirname(fpath),
'rootdir': os.path.dirname(os.path.dirname(fpath)),
'cmd': ' '.join(args),
@@ -337,18 +340,35 @@ def startup(ctx):
cluster_setup_with_admin_party(ctx)
else:
cluster_setup(ctx)
-
+ if ctx['degrade_cluster'] > 0:
+ degrade_cluster(ctx)
def kill_processes(ctx):
for proc in ctx['procs']:
if proc and proc.returncode is None:
proc.kill()
+def degrade_cluster(ctx):
+ if ctx['with_haproxy']:
+ haproxy_proc = ctx['procs'].pop()
+ for i in range(0,ctx['degrade_cluster']):
+ proc = ctx['procs'].pop()
+ if proc is not None:
+ kill_process(proc)
+ if ctx['with_haproxy']:
+ ctx['procs'].append(haproxy_proc)
+
+@log('Stoping proc {proc.pid}')
+def kill_process(proc):
+ if proc and proc.returncode is None:
+ proc.kill()
def boot_nodes(ctx):
for node in ctx['nodes']:
ctx['procs'].append(boot_node(ctx, node))
- ctx['procs'].append(boot_haproxy(ctx))
+ haproxy_proc = boot_haproxy(ctx)
+ if haproxy_proc is not None:
+ ctx['procs'].append(haproxy_proc)
def ensure_all_nodes_alive(ctx):
diff --git a/src/fabric/src/fabric_db_create.erl b/src/fabric/src/fabric_db_create.erl
index d793f4f13..db914f90e 100644
--- a/src/fabric/src/fabric_db_create.erl
+++ b/src/fabric/src/fabric_db_create.erl
@@ -146,9 +146,9 @@ maybe_stop(W, Counters) ->
{ok, {W, Counters}};
false ->
case lists:sum([1 || {_, ok} <- Counters]) of
- W ->
+ NumOk when NumOk >= (W div 2 +1) ->
{stop, ok};
- NumOk when NumOk >= (W div 2 + 1) ->
+ NumOk when NumOk > 0 ->
{stop, accepted};
_ ->
{error, internal_server_error}
diff --git a/test/javascript/run b/test/javascript/run
index c611be51e..8ae424467 100755
--- a/test/javascript/run
+++ b/test/javascript/run
@@ -107,7 +107,10 @@ def options():
dest="ignore", help="Ignore test suites"),
op.make_option("-u", "--suites", type="string", action="callback",
default=None, callback=get_delimited_list,
- dest="suites", help="Run specific suites")
+ dest="suites", help="Run specific suites"),
+ op.make_option("-p", "--path", type="string",
+ default="test/javascript/tests",
+ dest="test_path", help="Path where the tests are located")
]
@@ -118,10 +121,9 @@ def main():
run_list = []
ignore_list = []
tests = []
-
- run_list = ["test/javascript/tests"] if not opts.suites else opts.suites
- run_list = build_test_case_paths(run_list)
- ignore_list = build_test_case_paths(opts.ignore)
+ run_list = [opts.test_path] if not opts.suites else opts.suites
+ run_list = build_test_case_paths(opts.test_path,run_list)
+ ignore_list = build_test_case_paths(opts.test_path,opts.ignore)
# sort is needed because certain tests fail if executed out of order
tests = sorted(list(set(run_list)-set(ignore_list)))
@@ -151,7 +153,7 @@ def main():
failed, passed) + os.linesep)
exit(failed > 0)
-def build_test_case_paths(args=None):
+def build_test_case_paths(path,args=None):
tests = []
if args is None:
args = []
@@ -161,7 +163,7 @@ def build_test_case_paths(args=None):
elif os.path.isfile(name):
check = tests.append(name)
else:
- pname = os.path.join("test/javascript/tests", name)
+ pname = os.path.join(path, name)
if os.path.isfile(pname):
tests.append(pname)
elif os.path.isfile(pname + ".js"):
diff --git a/test/javascript/tests-cluster/with-quorum/db-creation.js b/test/javascript/tests-cluster/with-quorum/db-creation.js
new file mode 100644
index 000000000..f8efd6e68
--- /dev/null
+++ b/test/javascript/tests-cluster/with-quorum/db-creation.js
@@ -0,0 +1,27 @@
+// 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.
+
+// Do DB creation under cluster with quorum conditions.
+couchTests.db_creation = function(debug) {
+
+ if (debug) debugger;
+
+ var db_name = get_random_db_name()
+ var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
+
+ // DB Creation should return 201 - Created
+ xhr = CouchDB.request("PUT", "/" + db_name + "/");
+ T(xhr.status == 201);
+
+ // cleanup
+ db.deleteDb();
+};
diff --git a/test/javascript/tests-cluster/without-quorum/db-creation.js b/test/javascript/tests-cluster/without-quorum/db-creation.js
new file mode 100644
index 000000000..0d8ff8367
--- /dev/null
+++ b/test/javascript/tests-cluster/without-quorum/db-creation.js
@@ -0,0 +1,28 @@
+// 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.
+
+// Do DB creation under cluster without quorum conditions.
+couchTests.db_creation = function(debug) {
+
+ if (debug) debugger;
+
+ var db_name = get_random_db_name()
+ var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
+
+ // DB Creation should return 202- Accepted
+ xhr = CouchDB.request("PUT", "/" + db_name + "/");
+ T(xhr.status == 202);
+
+ // cleanup
+ // TODO DB deletions fails if the quorum is not met.
+ xhr = CouchDB.request("DELETE", "/" + db_name + "/");
+};