summaryrefslogtreecommitdiff
path: root/test/suite
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2016-02-22 10:10:55 -0500
committerKeith Bostic <keith@wiredtiger.com>2016-02-22 10:10:55 -0500
commit8a374c1b0a6f9291dcd7210695667c4871ebec86 (patch)
tree4c7dc0a73f2be1a4967f4931393f1edb18166980 /test/suite
parentb7cb64083d7192a831f810b60964954608c51045 (diff)
parentb27cac37d6b05157b65c07f7c85faf85f17f5f9e (diff)
downloadmongo-8a374c1b0a6f9291dcd7210695667c4871ebec86.tar.gz
Merge branch 'develop' into wt-2394
Diffstat (limited to 'test/suite')
-rw-r--r--test/suite/test_checkpoint01.py10
-rw-r--r--test/suite/test_cursor06.py5
-rw-r--r--test/suite/test_cursor_random.py24
-rw-r--r--test/suite/test_join01.py9
-rw-r--r--test/suite/test_readonly01.py143
-rw-r--r--test/suite/test_readonly02.py118
-rw-r--r--test/suite/test_readonly03.py125
-rw-r--r--test/suite/wttest.py8
8 files changed, 424 insertions, 18 deletions
diff --git a/test/suite/test_checkpoint01.py b/test/suite/test_checkpoint01.py
index 7d4503b84b7..36f1ef733a4 100644
--- a/test/suite/test_checkpoint01.py
+++ b/test/suite/test_checkpoint01.py
@@ -265,9 +265,13 @@ class test_checkpoint_cursor_update(wttest.WiredTigerTestCase):
cursor = self.session.open_cursor(self.uri, None, "checkpoint=ckpt")
cursor.set_key(key_populate(cursor, 10))
cursor.set_value("XXX")
- self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.insert())
- self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.remove())
- self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.update())
+ msg = "/not supported/"
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: cursor.insert(), msg)
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: cursor.remove(), msg)
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: cursor.update(), msg)
cursor.close()
diff --git a/test/suite/test_cursor06.py b/test/suite/test_cursor06.py
index ff7c1144344..d702f97c5dd 100644
--- a/test/suite/test_cursor06.py
+++ b/test/suite/test_cursor06.py
@@ -89,10 +89,11 @@ class test_cursor06(wttest.WiredTigerTestCase):
self.session.drop(uri, "force")
self.populate(uri)
cursor = self.session.open_cursor(uri, None, open_config)
+ msg = '/not supported/'
if open_config == "readonly=1":
self.set_kv(cursor)
- self.assertRaises(wiredtiger.WiredTigerError,
- lambda: cursor.update())
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: cursor.update(), msg)
else:
self.set_kv(cursor)
cursor.update()
diff --git a/test/suite/test_cursor_random.py b/test/suite/test_cursor_random.py
index 1fd30d93c11..cd91a925b0c 100644
--- a/test/suite/test_cursor_random.py
+++ b/test/suite/test_cursor_random.py
@@ -51,15 +51,21 @@ class test_cursor_random(wttest.WiredTigerTestCase):
uri = self.type
self.session.create(uri, 'key_format=S,value_format=S')
cursor = self.session.open_cursor(uri, None, self.config)
- self.assertRaises(
- wiredtiger.WiredTigerError, lambda: cursor.compare(cursor))
- self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.insert())
- self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.prev())
- self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.remove())
- self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.search())
- self.assertRaises(
- wiredtiger.WiredTigerError, lambda: cursor.search_near())
- self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.update())
+ msg = "/not supported/"
+ self.assertRaisesWithMessage(
+ wiredtiger.WiredTigerError, lambda: cursor.compare(cursor), msg)
+ self.assertRaisesWithMessage(
+ wiredtiger.WiredTigerError, lambda: cursor.insert(), msg)
+ self.assertRaisesWithMessage(
+ wiredtiger.WiredTigerError, lambda: cursor.prev(), msg)
+ self.assertRaisesWithMessage(
+ wiredtiger.WiredTigerError, lambda: cursor.remove(), msg)
+ self.assertRaisesWithMessage(
+ wiredtiger.WiredTigerError, lambda: cursor.search(), msg)
+ self.assertRaisesWithMessage(
+ wiredtiger.WiredTigerError, lambda: cursor.search_near(), msg)
+ self.assertRaisesWithMessage(
+ wiredtiger.WiredTigerError, lambda: cursor.update(), msg)
self.assertTrue(cursor.next(), wiredtiger.WT_NOTFOUND)
self.assertEquals(cursor.reconfigure(), 0)
diff --git a/test/suite/test_join01.py b/test/suite/test_join01.py
index f03c7c6f06c..ee4d6e22870 100644
--- a/test/suite/test_join01.py
+++ b/test/suite/test_join01.py
@@ -342,11 +342,12 @@ class test_join01(wttest.WiredTigerTestCase):
'/index cursor is being used in a join/')
# Only a small number of operations allowed on a join cursor
- self.assertRaises(wiredtiger.WiredTigerError,
- lambda: jc.search())
+ msg = "/not supported/"
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: jc.search(), msg)
- self.assertRaises(wiredtiger.WiredTigerError,
- lambda: jc.prev())
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: jc.prev(), msg)
self.assertEquals(jc.next(), 0)
self.assertEquals(jc.next(), wiredtiger.WT_NOTFOUND)
diff --git a/test/suite/test_readonly01.py b/test/suite/test_readonly01.py
new file mode 100644
index 00000000000..86604eb6bfb
--- /dev/null
+++ b/test/suite/test_readonly01.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+#
+# Public Domain 2016-2016 MongoDB, Inc.
+# Public Domain 2008-2016 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# test_readonly01.py
+# Readonly: Test readonly mode.
+#
+
+import fnmatch, os, shutil, time
+from suite_subprocess import suite_subprocess
+from wtscenario import multiply_scenarios, number_scenarios, prune_scenarios
+import wttest
+
+class test_readonly01(wttest.WiredTigerTestCase, suite_subprocess):
+ tablename = 'test_readonly01'
+ create = True
+ entries = 10000
+
+ #
+ # We want a list of directory writable or readonly.
+ #
+ basecfg_list = [
+ ('basecfg', dict(basecfg='config_base=true,')),
+ ('no_basecfg', dict(basecfg='config_base=false,')),
+ ]
+ dir_list = [
+ ('write', dict(dirchmod=False)),
+ ('readonly', dict(dirchmod=True)),
+ ]
+ log_list = [
+ ('logging', dict(logcfg='log=(archive=false,enabled,file_max=100K),')),
+ ('no_logging', dict(logcfg='log=(enabled=false),')),
+ ]
+
+ types = [
+ ('lsm', dict(tabletype='lsm', uri='lsm',
+ create_params = 'key_format=i,value_format=i')),
+ ('file-row', dict(tabletype='row', uri='file',
+ create_params = 'key_format=i,value_format=i')),
+ ('file-var', dict(tabletype='var', uri='file',
+ create_params = 'key_format=r,value_format=i')),
+ ('file-fix', dict(tabletype='fix', uri='file',
+ create_params = 'key_format=r,value_format=8t')),
+ ('table-row', dict(tabletype='row', uri='table',
+ create_params = 'key_format=i,value_format=i')),
+ ('table-var', dict(tabletype='var', uri='table',
+ create_params = 'key_format=r,value_format=i')),
+ ('table-fix', dict(tabletype='fix', uri='table',
+ create_params = 'key_format=r,value_format=8t')),
+ ]
+
+ scenarios = multiply_scenarios('.',
+ basecfg_list, dir_list, log_list, types)
+
+ def conn_config(self, dir):
+ self.home = dir
+ params = \
+ 'error_prefix="%s",' % self.shortid() + \
+ '%s' % self.logcfg + \
+ '%s' % self.basecfg
+ if self.create:
+ conn_params = 'create,' + params
+ else:
+ conn_params = 'readonly=true,' + params
+ return conn_params
+
+ def close_reopen(self):
+ ''' Close the connection and reopen readonly'''
+ #
+ # close the original connection. If needed, chmod the
+ # database directory to readonly mode. Then reopen the
+ # connection with readonly.
+ #
+ self.close_conn()
+ if self.dirchmod:
+ for f in os.listdir(self.home):
+ if os.path.isfile(f):
+ os.chmod(f, 0444)
+ os.chmod(self.home, 0555)
+ self.conn = self.setUpConnectionOpen(self.home)
+ self.session = self.setUpSessionOpen(self.conn)
+
+ def readonly(self):
+ # Here's the strategy:
+ # - Create a table.
+ # - Insert data into table.
+ # - Close connection.
+ # - Possibly chmod to readonly
+ # - Open connection readonly
+ # - Confirm we can read the data.
+ #
+ tablearg = self.uri + ':' + self.tablename
+ self.session.create(tablearg, self.create_params)
+ c = self.session.open_cursor(tablearg, None, None)
+ for i in range(self.entries):
+ c[i+1] = i % 255
+ # Close the connection. Reopen readonly
+ self.create = False
+ self.close_reopen()
+ c = self.session.open_cursor(tablearg, None, None)
+ i = 0
+ for key, value in c:
+ self.assertEqual(i+1, key)
+ self.assertEqual(i % 255, value)
+ i += 1
+ self.assertEqual(i, self.entries)
+ self.pr('Read %d entries' % i)
+ c.close()
+ self.create = True
+
+ def test_readonly(self):
+ if self.dirchmod:
+ with self.expectedStderrPattern('Permission'):
+ self.readonly()
+ else:
+ self.readonly()
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/test/suite/test_readonly02.py b/test/suite/test_readonly02.py
new file mode 100644
index 00000000000..e94dd85857d
--- /dev/null
+++ b/test/suite/test_readonly02.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+#
+# Public Domain 2016-2016 MongoDB, Inc.
+# Public Domain 2008-2016 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# test_readonly02.py
+# Readonly: Test readonly mode with illegal config combinations
+# and error checking during updates.
+#
+
+from helper import copy_wiredtiger_home
+from suite_subprocess import suite_subprocess
+import os, wiredtiger, wttest
+
+class test_readonly02(wttest.WiredTigerTestCase, suite_subprocess):
+ tablename = 'table:test_readonly02'
+ create = True
+ create_params = 'key_format=i,value_format=i'
+ entries = 10
+
+ conn_params = \
+ 'create,statistics=(fast),log=(enabled,file_max=100K,zero_fill=true),'
+ conn_params_rd = \
+ 'create,readonly=true,statistics=(fast),log=(enabled,zero_fill=false),'
+ conn_params_rdcfg = \
+ 'create,readonly=true,statistics=(fast),log=(enabled),'
+
+ #
+ # Run to make sure incompatible configuration options return an error.
+ # The situations that cause failures (instead of silent overrides) are:
+ # 1. setting readonly on a new database directory
+ # 2. an unclean shutdown and reopening readonly
+ # 3. logging with zero-fill enabled and readonly
+ # 4. readonly and statistics logging
+ #
+ badcfg1 = 'log=(enabled,zero_fill=true)'
+ badcfg2 = 'statistics_log=(wait=3)'
+
+ def setUpConnectionOpen(self, dir):
+ self.home = dir
+ rdonlydir = dir + '.rdonly'
+ #
+ # First time through check readonly on a non-existent database.
+ #
+ if self.create:
+ # 1. setting readonly on a new database directory
+ # Setting readonly prevents creation so we should see an
+ # ENOENT error because the lock file does not exist.
+ msg = '/No such file/'
+ os.mkdir(rdonlydir)
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.wiredtiger_open(
+ rdonlydir, self.conn_params_rd), msg)
+
+ self.create = False
+ conn = self.wiredtiger_open(dir, self.conn_params)
+ return conn
+
+ def check_unclean(self):
+ backup = "WT_COPYDIR"
+ copy_wiredtiger_home(self.home, backup, True)
+ msg = '/needs recovery/'
+ # 2. an unclean shutdown and reopening readonly
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.wiredtiger_open(backup, self.conn_params_rd), msg)
+
+ def close_checkerror(self, cfg):
+ ''' Close the connection and reopen readonly'''
+ #
+ # Close the original connection. Reopen readonly and also with
+ # the given configuration string.
+ #
+ self.close_conn()
+ conn_params = self.conn_params_rd + cfg
+ msg = '/Invalid argument/'
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.wiredtiger_open(self.home, conn_params), msg)
+
+ def test_readonly(self):
+ tablearg = self.tablename
+ self.session.create(tablearg, self.create_params)
+ c = self.session.open_cursor(tablearg, None, None)
+ for i in range(self.entries):
+ c[i+1] = i % 255
+ # Check for an error on an unclean recovery/restart.
+ self.check_unclean()
+
+ # Close the connection. Reopen readonly with other bad settings.
+ # 3. logging with zero-fill enabled and readonly
+ self.close_checkerror(self.badcfg1)
+ # 4. readonly and statistics logging
+ self.close_checkerror(self.badcfg2)
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/test/suite/test_readonly03.py b/test/suite/test_readonly03.py
new file mode 100644
index 00000000000..981a21d51ac
--- /dev/null
+++ b/test/suite/test_readonly03.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+#
+# Public Domain 2016-2016 MongoDB, Inc.
+# Public Domain 2008-2016 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# test_readonly03.py
+# Readonly: Test connection readonly mode with modifying methods. Confirm
+# all return ENOTSUP.
+#
+
+from helper import simple_populate
+from suite_subprocess import suite_subprocess
+import os, sys, wiredtiger, wttest
+
+class test_readonly03(wttest.WiredTigerTestCase, suite_subprocess):
+ uri = 'table:test_readonly03'
+ uri2 = 'table:test_readonly03_2'
+ create = True
+
+ conn_params = 'create,log=(enabled),'
+ conn_params_rd = 'readonly=true'
+
+ session_ops = [ 'create', 'compact', 'drop', 'log_flush', 'log_printf',
+ 'rebalance', 'rename', 'salvage', 'truncate', 'upgrade', ]
+ cursor_ops = [ 'insert', 'remove', 'update', ]
+
+ def setUpConnectionOpen(self, dir):
+ self.home = dir
+ if self.create:
+ conn_cfg = self.conn_params
+ else:
+ conn_cfg = self.conn_params_rd
+ conn = self.wiredtiger_open(dir, conn_cfg)
+ self.create = False
+ return conn
+
+
+ def test_readonly(self):
+ create_params = 'key_format=i,value_format=i'
+ entries = 10
+ # Create a database and a table.
+ simple_populate(self, self.uri, create_params, entries)
+
+ #
+ # Now close and reopen. Note that the connection function
+ # above will reopen it readonly.
+ self.reopen_conn()
+ msg = '/not supported/'
+ c = self.session.open_cursor(self.uri, None, None)
+ for op in self.cursor_ops:
+ c.set_key(1)
+ c.set_value(1)
+ if op == 'insert':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: c.insert(), msg)
+ elif op == 'remove':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: c.remove(), msg)
+ elif op == 'update':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: c.update(), msg)
+ else:
+ self.fail('Unknown cursor operation: ' + op)
+ c.close()
+ for op in self.session_ops:
+ if op == 'create':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.session.create(self.uri2, create_params),
+ msg)
+ elif op == 'compact':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.session.compact(self.uri, None), msg)
+ elif op == 'drop':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.session.drop(self.uri, None), msg)
+ elif op == 'log_flush':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.session.log_flush(None), msg)
+ elif op == 'log_printf':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.session.log_printf("test"), msg)
+ elif op == 'rebalance':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.session.rebalance(self.uri, None), msg)
+ elif op == 'rename':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.session.rename(self.uri, self.uri2, None), msg)
+ elif op == 'salvage':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.session.salvage(self.uri, None), msg)
+ elif op == 'truncate':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.session.truncate(self.uri, None, None, None),
+ msg)
+ elif op == 'upgrade':
+ self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
+ lambda: self.session.upgrade(self.uri, None), msg)
+ else:
+ self.fail('Unknown session method: ' + op)
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/test/suite/wttest.py b/test/suite/wttest.py
index b5a58d1566f..a1945b4325d 100644
--- a/test/suite/wttest.py
+++ b/test/suite/wttest.py
@@ -335,6 +335,14 @@ class WiredTigerTestCase(unittest.TestCase):
# always get back to original directory
os.chdir(self.origcwd)
+ # Make sure no read-only files or directories were left behind
+ os.chmod(self.testdir, 0777)
+ for root, dirs, files in os.walk(self.testdir):
+ for d in dirs:
+ os.chmod(os.path.join(root, d), 0777)
+ for f in files:
+ os.chmod(os.path.join(root, f), 0666)
+
# Clean up unless there's a failure
if (passed or skipped) and not WiredTigerTestCase._preserveFiles:
shutil.rmtree(self.testdir, ignore_errors=True)