summaryrefslogtreecommitdiff
path: root/test/suite
diff options
context:
space:
mode:
authorDavid Hows <david.hows@mongodb.com>2017-01-06 12:12:50 +1100
committerDavid Hows <david.hows@mongodb.com>2017-01-06 12:12:50 +1100
commitd48181f6f4db08761ed7b80b0332908b272ad0d0 (patch)
tree38929fdcc5415ee7b001b6f1a406bd5bd777b737 /test/suite
parent040e3d6f764c0fb626cb47fede54469f57d0c6e0 (diff)
parent8d2324943364286056ae399043f70b8a937de312 (diff)
downloadmongo-d48181f6f4db08761ed7b80b0332908b272ad0d0.tar.gz
Merge branch 'mongodb-3.6' into mongodb-3.2mongodb-3.2.12
Diffstat (limited to 'test/suite')
-rw-r--r--test/suite/test_alter01.py169
-rw-r--r--test/suite/test_bug011.py15
-rw-r--r--test/suite/test_compact02.py17
-rw-r--r--test/suite/test_config03.py10
-rw-r--r--test/suite/test_config04.py4
-rw-r--r--test/suite/test_cursor10.py127
-rw-r--r--test/suite/test_hazard.py58
-rw-r--r--test/suite/test_index02.py71
-rw-r--r--test/suite/test_inmem01.py51
-rw-r--r--test/suite/test_join01.py9
-rw-r--r--test/suite/test_nsnap04.py37
-rw-r--r--test/suite/wtdataset.py4
12 files changed, 528 insertions, 44 deletions
diff --git a/test/suite/test_alter01.py b/test/suite/test_alter01.py
new file mode 100644
index 00000000000..dfdf6b7a17e
--- /dev/null
+++ b/test/suite/test_alter01.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2016 MongoDB, Inc.
+# Public Domain 2008-2014 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.
+
+import wiredtiger, wttest
+from wtscenario import make_scenarios
+
+# test_alter01.py
+# Smoke-test the session alter operations.
+class test_alter01(wttest.WiredTigerTestCase):
+ name = "alter01"
+ entries = 100
+ # Settings for access_pattern_hint
+ types = [
+ ('file', dict(uri='file:', use_cg=False, use_index=False)),
+ ('lsm', dict(uri='lsm:', use_cg=False, use_index=False)),
+ ('table-cg', dict(uri='table:', use_cg=True, use_index=False)),
+ ('table-index', dict(uri='table:', use_cg=False, use_index=True)),
+ ('table-simple', dict(uri='table:', use_cg=False, use_index=False)),
+ ]
+ hints = [
+ ('default', dict(acreate='')),
+ ('none', dict(acreate='none')),
+ ('random', dict(acreate='random')),
+ ('sequential', dict(acreate='sequential')),
+ ]
+ access_alter=('', 'none', 'random', 'sequential')
+ # Settings for cache_resident
+ resid = [
+ ('default', dict(ccreate='')),
+ ('false', dict(ccreate='false')),
+ ('true', dict(ccreate='true')),
+ ]
+ reopen = [
+ ('no-reopen', dict(reopen=False)),
+ ('reopen', dict(reopen=True)),
+ ]
+ cache_alter=('', 'false', 'true')
+ scenarios = make_scenarios(types, hints, resid, reopen)
+
+ def verify_metadata(self, metastr):
+ if metastr == '':
+ return
+ cursor = self.session.open_cursor('metadata:', None, None)
+ #
+ # Walk through all the metadata looking for the entries that are
+ # the file URIs for components of the table.
+ #
+ found = False
+ while True:
+ ret = cursor.next()
+ if ret != 0:
+ break
+ key = cursor.get_key()
+ check_meta = ((key.find("lsm:") != -1 or key.find("file:") != -1) \
+ and key.find(self.name) != -1)
+ if check_meta:
+ value = cursor[key]
+ found = True
+ self.assertTrue(value.find(metastr) != -1)
+ cursor.close()
+ self.assertTrue(found == True)
+
+ # Alter: Change the access pattern hint after creation
+ def test_alter01_access(self):
+ uri = self.uri + self.name
+ create_params = 'key_format=i,value_format=i,'
+ complex_params = ''
+ #
+ # If we're not explicitly setting the parameter, then don't
+ # modify create_params to test using the default.
+ #
+ if self.acreate != '':
+ access_param = 'access_pattern_hint=%s' % self.acreate
+ create_params += '%s,' % access_param
+ complex_params += '%s,' % access_param
+ else:
+ # NOTE: This is hard-coding the default value. If the default
+ # changes then this will fail and need to be fixed.
+ access_param = 'access_pattern_hint=none'
+ if self.ccreate != '':
+ cache_param = 'cache_resident=%s' % self.ccreate
+ create_params += '%s,' % cache_param
+ complex_params += '%s,' % cache_param
+ else:
+ # NOTE: This is hard-coding the default value. If the default
+ # changes then this will fail and need to be fixed.
+ cache_param = 'cache_resident=false'
+
+ cgparam = ''
+ if self.use_cg or self.use_index:
+ cgparam = 'columns=(k,v),'
+ if self.use_cg:
+ cgparam += 'colgroups=(g0),'
+
+ self.session.create(uri, create_params + cgparam)
+ # Add in column group or index settings.
+ if self.use_cg:
+ cgparam = 'columns=(v),'
+ suburi = 'colgroup:' + self.name + ':g0'
+ self.session.create(suburi, complex_params + cgparam)
+ if self.use_index:
+ suburi = 'index:' + self.name + ':i0'
+ self.session.create(suburi, complex_params + cgparam)
+
+ # Put some data in table.
+ c = self.session.open_cursor(uri, None)
+ for k in range(self.entries):
+ c[k+1] = 1
+ c.close()
+
+ # Verify the string in the metadata
+ self.verify_metadata(access_param)
+ self.verify_metadata(cache_param)
+
+ # Run through all combinations of the alter commands
+ # for all allowed settings. This tests having only one or
+ # the other set as well as having both set. It will also
+ # cover trying to change the setting to its current value.
+ for a in self.access_alter:
+ alter_param = ''
+ access_str = ''
+ if a != '':
+ access_str = 'access_pattern_hint=%s' % a
+ for c in self.cache_alter:
+ alter_param = '%s' % access_str
+ cache_str = ''
+ if c != '':
+ cache_str = 'cache_resident=%s' % c
+ alter_param += ',%s' % cache_str
+ if alter_param != '':
+ self.session.alter(uri, alter_param)
+ if self.reopen:
+ self.reopen_conn()
+ special = self.use_cg or self.use_index
+ if not special:
+ self.verify_metadata(access_str)
+ self.verify_metadata(cache_str)
+ else:
+ self.session.alter(suburi, alter_param)
+ self.verify_metadata(access_str)
+ self.verify_metadata(cache_str)
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/test/suite/test_bug011.py b/test/suite/test_bug011.py
index 29bb08ec2e5..969aaeb5b39 100644
--- a/test/suite/test_bug011.py
+++ b/test/suite/test_bug011.py
@@ -30,25 +30,28 @@ import random, wiredtiger, wttest
from wtdataset import SimpleDataSet
# test_bug011.py
-# Eviction working on more files than there are hazard pointers.
+# Eviction working on more trees than the eviction server can walk
+# simultaneously. There is a builtin limit of 1000 trees, we open double
+# that, which makes this a long-running test.
class test_bug011(wttest.WiredTigerTestCase):
"""
Test having eviction working on more files than the number of
allocated hazard pointers.
"""
table_name = 'test_bug011'
- ntables = 50
+ ntables = 2000
nrows = 10000
nops = 10000
# Add connection configuration for this test.
def conn_config(self, dir):
- return 'cache_size=10MB,eviction_dirty_target=99,eviction_dirty_trigger=99,hazard_max=' + str(self.ntables / 2)
+ return 'cache_size=1GB'
+ @wttest.longtest("Eviction copes with lots of files")
def test_eviction(self):
cursors = []
datasets = []
for i in range(0, self.ntables):
- this_uri = 'table:%s-%03d' % (self.table_name, i)
+ this_uri = 'table:%s-%05d' % (self.table_name, i)
ds = SimpleDataSet(self, this_uri, self.nrows,
config='allocation_size=1KB,leaf_page_max=1KB')
ds.populate()
@@ -57,9 +60,9 @@ class test_bug011(wttest.WiredTigerTestCase):
# Switch over to on-disk trees with multiple leaf pages
self.reopen_conn()
- # Make sure we have a cursor for the table so it stays in cache.
+ # Make sure we have a cursor for every table so it stays in cache.
for i in range(0, self.ntables):
- this_uri = 'table:%s-%03d' % (self.table_name, i)
+ this_uri = 'table:%s-%05d' % (self.table_name, i)
cursors.append(self.session.open_cursor(this_uri, None))
# Make use of the cache.
diff --git a/test/suite/test_compact02.py b/test/suite/test_compact02.py
index 3a4ca6cbc7e..7af76b5fd58 100644
--- a/test/suite/test_compact02.py
+++ b/test/suite/test_compact02.py
@@ -38,7 +38,7 @@ from wtscenario import make_scenarios
class test_compact02(wttest.WiredTigerTestCase):
types = [
- ('file', dict(uri='file:test_compact02')),
+ ('table', dict(uri='table:test_compact02')),
]
cacheSize = [
('default', dict(cacheSize='')),
@@ -69,8 +69,9 @@ class test_compact02(wttest.WiredTigerTestCase):
# 1. Create a table with the data, alternating record size.
# 2. Checkpoint and get stats on the table to confirm the size.
# 3. Delete the half of the records with the larger record size.
- # 4. Call compact.
- # 5. Get stats on compacted table.
+ # 4. Checkpoint so compact finds something to work with.
+ # 5. Call compact.
+ # 6. Get stats on compacted table.
#
nrecords = 22000
bigvalue = "abcdefghi" * 1074 # 9*1074 == 9666
@@ -99,7 +100,8 @@ class test_compact02(wttest.WiredTigerTestCase):
self.home = '.'
conn_params = 'create,' + \
cacheSize + ',error_prefix="%s: ",' % self.shortid() + \
- 'statistics=(all),eviction_dirty_target=99,eviction_dirty_trigger=99'
+ 'statistics=(all),' + \
+ 'eviction_dirty_target=99,eviction_dirty_trigger=99'
try:
self.conn = wiredtiger.wiredtiger_open(self.home, conn_params)
except wiredtiger.WiredTigerError as e:
@@ -140,10 +142,13 @@ class test_compact02(wttest.WiredTigerTestCase):
c.close()
self.pr('Removed total ' + str((count * 9666) / mb) + 'MB')
- # 4. Call compact.
+ # 4. Checkpoint
+ self.session.checkpoint()
+
+ # 5. Call compact.
self.session.compact(self.uri, None)
- # 5. Get stats on compacted table.
+ # 6. Get stats on compacted table.
sz = self.getSize()
self.pr('After compact ' + str(sz / mb) + 'MB')
diff --git a/test/suite/test_config03.py b/test/suite/test_config03.py
index 88ca6ae3f39..6699f7d2650 100644
--- a/test/suite/test_config03.py
+++ b/test/suite/test_config03.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!usr/bin/env python
#
# Public Domain 2014-2016 MongoDB, Inc.
# Public Domain 2008-2014 WiredTiger, Inc.
@@ -48,8 +48,6 @@ class test_config03(test_base03.test_base03):
eviction_trigger_scenarios = wtscenario.quick_scenarios(
's_eviction_trigger',
[50, 90, 95, 99], None)
- hazard_max_scenarios = wtscenario.quick_scenarios('s_hazard_max',
- [15, 50, 500], [0.4, 0.8, 0.8])
multiprocess_scenarios = wtscenario.quick_scenarios('s_multiprocess',
[True,False], [1.0,1.0])
session_max_scenarios = wtscenario.quick_scenarios('s_session_max',
@@ -66,13 +64,13 @@ class test_config03(test_base03.test_base03):
verbose_scenarios = wtscenario.quick_scenarios('s_verbose', [None], None)
config_vars = [ 'cache_size', 'create', 'error_prefix', 'eviction_target',
- 'eviction_trigger', 'hazard_max', 'multiprocess',
- 'session_max', 'verbose' ]
+ 'eviction_trigger', 'multiprocess', 'session_max',
+ 'verbose' ]
scenarios = wtscenario.make_scenarios(
cache_size_scenarios, create_scenarios, error_prefix_scenarios,
eviction_target_scenarios, eviction_trigger_scenarios,
- hazard_max_scenarios, multiprocess_scenarios, session_max_scenarios,
+ multiprocess_scenarios, session_max_scenarios,
transactional_scenarios, verbose_scenarios, prune=1000)
#wttest.WiredTigerTestCase.printVerbose(2, 'test_config03: running ' + \
diff --git a/test/suite/test_config04.py b/test/suite/test_config04.py
index 204aa7e27d5..db8a5f4a16a 100644
--- a/test/suite/test_config04.py
+++ b/test/suite/test_config04.py
@@ -154,10 +154,6 @@ class test_config04(wttest.WiredTigerTestCase):
'eviction_trigger=86'),
"/eviction target must be lower than the eviction trigger/")
- def test_hazard_max(self):
- # Note: There isn't any direct way to know that this was set.
- self.common_test('hazard_max=50')
-
def test_invalid_config(self):
msg = '/Unbalanced brackets/'
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
diff --git a/test/suite/test_cursor10.py b/test/suite/test_cursor10.py
new file mode 100644
index 00000000000..b3cffeab4e9
--- /dev/null
+++ b/test/suite/test_cursor10.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2016 MongoDB, Inc.
+# Public Domain 2008-2014 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.
+
+import wiredtiger, wttest
+from wtscenario import make_scenarios
+
+# test_cursor10.py
+# Cursors with projections.
+class test_cursor04(wttest.WiredTigerTestCase):
+ """
+ Test cursor search and search_near
+ """
+ table_name1 = 'test_cursor04'
+ nentries = 20
+
+ scenarios = make_scenarios([
+ ('row', dict(key_format='S', uri='table')),
+ ('col', dict(key_format='r', uri='table'))
+ ])
+
+ def genkey(self, i):
+ if self.key_format == 'S':
+ return 'key' + str(i).zfill(5) # return key00001, key00002, etc.
+ else:
+ return long(i+1)
+
+ def genvalue(self, i):
+ return [ 'v0:' + str(i), i+1, 'v2' + str(i+2), i+3 ]
+
+ def extractkey(self, k):
+ if self.key_format == 'S':
+ return int(k[3:])
+ else:
+ return long(k-1)
+
+ def test_projection(self):
+ """
+ Create entries, and read back in a regular and projected cursor
+ """
+ tablearg = self.uri + ":" + self.table_name1
+ create_args = 'columns=(k,v0,v1,v2,v3),value_format=SiSi,key_format=' \
+ + self.key_format
+ self.session.create(tablearg, create_args)
+
+ cursor = self.session.open_cursor(tablearg, None, None)
+ for i in range(0, self.nentries):
+ cursor.set_key(self.genkey(i))
+ values = self.genvalue(i)
+ cursor.set_value(*values)
+ cursor.insert()
+ cursor.close()
+ cursor = self.session.open_cursor(tablearg, None, None)
+ count = 0
+ for k,v0,v1,v2,v3 in cursor:
+ i = self.extractkey(k)
+ self.assertEqual(self.genkey(i), k)
+ self.assertEqual(self.genvalue(i), [v0,v1,v2,v3])
+ count += 1
+ self.assertEqual(count, self.nentries)
+ cursor.close()
+ cursor = self.session.open_cursor(tablearg + '(v3,v2,v1,v0,k)',\
+ None, None)
+ count = 0
+ for k1,v3,v2,v1,v0,k2 in cursor:
+ self.assertEqual(k1, k2)
+ i = self.extractkey(k1)
+ self.assertEqual(self.genkey(i), k1)
+ self.assertEqual(self.genvalue(i), [v0,v1,v2,v3])
+ count += 1
+ self.assertEqual(count, self.nentries)
+ cursor.close()
+
+ def test_index_projection(self):
+ """
+ Create entries, and read back in an index cursor with a projection
+ """
+ tablearg = self.uri + ":" + self.table_name1
+ indexarg = 'index:' + self.table_name1 + ':index1'
+ create_args = 'columns=(k,v0,v1,v2,v3),value_format=SiSi,key_format=' \
+ + self.key_format
+ self.session.create(tablearg, create_args)
+ self.session.create(indexarg, 'columns=(v0,v2,v1,v3)')
+ cursor = self.session.open_cursor(tablearg, None, None)
+ for i in range(0, self.nentries):
+ cursor.set_key(self.genkey(i))
+ values = self.genvalue(i)
+ cursor.set_value(*values)
+ cursor.insert()
+ cursor.close()
+ cursor = self.session.open_cursor(tablearg + '(v3,v2,v1,v0,k)',\
+ None, None)
+ count = 0
+ for k1,v3,v2,v1,v0,k2 in cursor:
+ self.assertEqual(k1, k2)
+ i = self.extractkey(k1)
+ self.assertEqual(self.genkey(i), k1)
+ self.assertEqual(self.genvalue(i), [v0,v1,v2,v3])
+ count += 1
+ self.assertEqual(count, self.nentries)
+ cursor.close()
+if __name__ == '__main__':
+ wttest.run()
diff --git a/test/suite/test_hazard.py b/test/suite/test_hazard.py
new file mode 100644
index 00000000000..f2891fce526
--- /dev/null
+++ b/test/suite/test_hazard.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2016 MongoDB, Inc.
+# Public Domain 2008-2014 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_hazard.py
+# Hazard pointer tests.
+
+import wiredtiger, wttest
+from wtdataset import SimpleDataSet
+
+# Regression tests.
+class test_hazard(wttest.WiredTigerTestCase):
+
+ # Allocate a large number of hazard pointers in a session, forcing the
+ # hazard pointer array to repeatedly grow.
+ def test_hazard(self):
+ uri = "table:hazard"
+ ds = SimpleDataSet(self, uri, 1000)
+ ds.populate()
+
+ # Open 10,000 cursors and pin a page to set a hazard pointer.
+ cursors = []
+ for i in range(0, 10000):
+ c = self.session.open_cursor(uri, None)
+ c.set_key(ds.key(10))
+ c.search()
+ cursors.append(c)
+
+ # Close the cursors, clearing the hazard pointer.
+ for c in cursors:
+ c.close()
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/test/suite/test_index02.py b/test/suite/test_index02.py
index 9f39df003b1..4f424e5d3d2 100644
--- a/test/suite/test_index02.py
+++ b/test/suite/test_index02.py
@@ -27,20 +27,26 @@
# OTHER DEALINGS IN THE SOFTWARE.
import wiredtiger, wttest
+from wtscenario import make_scenarios
# test_index02.py
# test search_near in indices
class test_index02(wttest.WiredTigerTestCase):
'''Test search_near in indices'''
+ scenarios = make_scenarios([
+ ('index', dict(indexconfig='columns=(v)', ncol=1)),
+ ('index-with-key', dict(indexconfig='columns=(v,k)', ncol=2)),
+ ])
+
basename = 'test_index02'
tablename = 'table:' + basename
indexname = 'index:' + basename + ":inverse"
- def test_search_near(self):
- '''Create a table, look for a nonexistent key'''
+ def test_search_near_exists(self):
+ '''Create a table, look for an existing key'''
self.session.create(self.tablename, 'key_format=r,value_format=Q,columns=(k,v)')
- self.session.create(self.indexname, 'columns=(v)')
+ self.session.create(self.indexname, self.indexconfig)
cur = self.session.open_cursor(self.tablename, None, "append")
cur.set_value(1)
cur.insert()
@@ -52,17 +58,60 @@ class test_index02(wttest.WiredTigerTestCase):
cur.insert()
cur.set_value(10)
cur.insert()
+ cur.close()
+
+ # Retry after reopening
+ for runs in xrange(2):
+ # search near should find a match
+ cur = self.session.open_cursor(self.indexname, None, None)
+ if self.ncol == 1:
+ cur.set_key(5)
+ else:
+ cur.set_key(5, 3)
+ self.assertEqual(cur.search_near(), 0)
+
+ # Retry after reopening
+ self.reopen_conn()
+
+ def test_search_near_between(self):
+ '''Create a table, look for a non-existing key'''
+ self.session.create(self.tablename, 'key_format=i,value_format=i,columns=(k,v)')
+ self.session.create(self.indexname, self.indexconfig)
+ cur = self.session.open_cursor(self.tablename)
+ for k in xrange(3):
+ cur[k] = 5 * k + 10
+ cur.close()
+
+ search_keys = [ 1, 11, 15, 19, 21 ]
# search near should find a match
- cur2 = self.session.open_cursor(self.indexname, None, None)
- cur2.set_key(5)
- self.assertEqual(cur2.search_near(), 0)
+ for runs in xrange(2):
+ cur = self.session.open_cursor(self.indexname, None, None)
+ for k in search_keys:
+ if self.ncol == 1:
+ cur.set_key(k)
+ else:
+ cur.set_key(k, 1) # [15,1] will completely match
+ exact = cur.search_near()
+ if self.ncol == 1:
+ found_key = cur.get_key()
+ else:
+ [ found_key, index ] = cur.get_key()
+ self.pr("search_near for " + str(k) + " found " + str(found_key) + " with exact " + str(exact))
+ self.assertEqual(exact, cmp(found_key, k), "for key " + str(k))
+ self.reopen_conn()
- # Retry after reopening
- self.reopen_conn()
- cur3 = self.session.open_cursor(self.indexname, None, None)
- cur3.set_key(5)
- self.assertEqual(cur3.search_near(), 0)
+ def test_search_near_empty(self):
+ '''Create an empty table, look for a key'''
+ self.session.create(self.tablename, 'key_format=i,value_format=i,columns=(k,v)')
+ self.session.create(self.indexname, self.indexconfig)
+
+ cur = self.session.open_cursor(self.indexname, None, None)
+ if self.ncol == 1:
+ cur.set_key(3)
+ else:
+ cur.set_key(3, 1)
+ self.assertEqual(cur.search_near(), wiredtiger.WT_NOTFOUND)
if __name__ == '__main__':
wttest.run()
diff --git a/test/suite/test_inmem01.py b/test/suite/test_inmem01.py
index 1af43bbd9d9..388485db29b 100644
--- a/test/suite/test_inmem01.py
+++ b/test/suite/test_inmem01.py
@@ -59,7 +59,7 @@ class test_inmem01(wttest.WiredTigerTestCase):
ds = SimpleDataSet(self, self.uri, 10000000, key_format=self.keyfmt,
value_format=self.valuefmt, config=self.table_config)
self.assertRaisesHavingMessage(wiredtiger.WiredTigerError,
- lambda:ds.populate(), msg)
+ ds.populate, msg)
# Figure out the last key we successfully inserted, and check all
# previous inserts are still there.
@@ -77,7 +77,7 @@ class test_inmem01(wttest.WiredTigerTestCase):
ds = SimpleDataSet(self, self.uri, 10000000, key_format=self.keyfmt,
value_format=self.valuefmt, config=self.table_config)
self.assertRaisesHavingMessage(wiredtiger.WiredTigerError,
- lambda:ds.populate(), msg)
+ ds.populate, msg)
# Now that the database contains as much data as will fit into
# the configured cache, verify removes succeed.
@@ -93,7 +93,7 @@ class test_inmem01(wttest.WiredTigerTestCase):
ds = SimpleDataSet(self, self.uri, 10000000, key_format=self.keyfmt,
value_format=self.valuefmt, config=self.table_config)
self.assertRaisesHavingMessage(wiredtiger.WiredTigerError,
- lambda:ds.populate(), msg)
+ ds.populate, msg)
cursor = self.session.open_cursor(self.uri, None)
cursor.prev()
@@ -120,5 +120,50 @@ class test_inmem01(wttest.WiredTigerTestCase):
break
self.assertTrue(inserted)
+ # Custom "keep filling" helper
+ def fill(self, cursor, ds, start, end):
+ for i in xrange(start + 1, end + 1):
+ cursor[ds.key(i)] = ds.value(i)
+
+ # Keep adding data to the cache until it becomes really full, make sure
+ # that reads aren't blocked.
+ @wttest.longtest("Try to wedge an in-memory cache")
+ def test_wedge(self):
+ # Try to really wedge the cache full
+ ds = SimpleDataSet(self, self.uri, 0, key_format=self.keyfmt,
+ value_format=self.valuefmt, config=self.table_config)
+ ds.populate()
+ cursor = self.session.open_cursor(self.uri, None)
+
+ run = 0
+ start, last_key = -1000, 0
+ while last_key - start > 100:
+ msg = '/WT_CACHE_FULL.*/'
+ start = last_key
+ self.assertRaisesHavingMessage(wiredtiger.WiredTigerError,
+ lambda: self.fill(cursor, ds, start, 10000000), msg)
+ cursor.reset()
+ sleep(1)
+
+ # Figure out the last key we successfully inserted, and check all
+ # previous inserts are still there.
+ cursor.prev()
+ last_key = int(cursor.get_key())
+ run += 1
+ self.pr('Finished iteration ' + str(run) + ', last_key = ' + str(last_key))
+
+ self.pr('Checking ' + str(last_key) + ' keys')
+ ds = SimpleDataSet(self, self.uri, last_key, key_format=self.keyfmt,
+ value_format=self.valuefmt, config=self.table_config)
+
+ # This test is *much* slower for fixed-length column stores: we fit
+ # many more records into the cache, so don't do as many passes through
+ # the data.
+ checks = 10 if self.valuefmt.endswith('t') else 100
+ for run in xrange(checks):
+ ds.check()
+ self.pr('Finished check ' + str(run))
+ sleep(1)
+
if __name__ == '__main__':
wttest.run()
diff --git a/test/suite/test_join01.py b/test/suite/test_join01.py
index f3b13026896..2c4328dc7d3 100644
--- a/test/suite/test_join01.py
+++ b/test/suite/test_join01.py
@@ -110,8 +110,9 @@ class test_join01(wttest.WiredTigerTestCase):
while jc.next() == 0:
[k] = jc.get_keys()
i = k - 1
- if do_proj: # our projection test simply reverses the values
- [v2,v1,v0] = jc.get_values()
+ if do_proj: # our projection reverses the values and adds the key
+ [v2,v1,v0,kproj] = jc.get_values()
+ self.assertEquals(k, kproj)
else:
[v0,v1,v2] = jc.get_values()
self.assertEquals(self.gen_values(i), [v0,v1,v2])
@@ -136,7 +137,7 @@ class test_join01(wttest.WiredTigerTestCase):
if self.ref == 'index':
expectstats.append('join: index:join01:index0: ' + statdesc)
elif self.do_proj:
- expectstats.append('join: table:join01(v2,v1,v0): ' + statdesc)
+ expectstats.append('join: table:join01(v2,v1,v0,k): ' + statdesc)
else:
expectstats.append('join: table:join01: ' + statdesc)
self.check_stats(statcur, expectstats)
@@ -228,7 +229,7 @@ class test_join01(wttest.WiredTigerTestCase):
c.close()
if do_proj:
- proj_suffix = '(v2,v1,v0)' # Reversed values
+ proj_suffix = '(v2,v1,v0,k)' # Reversed values plus key
else:
proj_suffix = '' # Default projection (v0,v1,v2)
diff --git a/test/suite/test_nsnap04.py b/test/suite/test_nsnap04.py
index 60901dd2ee3..8d491540d74 100644
--- a/test/suite/test_nsnap04.py
+++ b/test/suite/test_nsnap04.py
@@ -38,14 +38,18 @@ class test_nsnap04(wttest.WiredTigerTestCase, suite_subprocess):
uri = 'table:' + tablename
nrows_per_itr = 10
- def check_named_snapshot(self, snapshot, expected):
+ def check_named_snapshot(self, snapshot, expected, skip_snapshot=False):
new_session = self.conn.open_session()
c = new_session.open_cursor(self.uri)
- new_session.begin_transaction("snapshot=" + str(snapshot))
+ if skip_snapshot:
+ new_session.begin_transaction()
+ else:
+ new_session.begin_transaction("snapshot=" + str(snapshot))
count = 0
for row in c:
count += 1
new_session.commit_transaction()
+ new_session.close()
# print "Checking snapshot %d, expect %d, found %d" % (snapshot, expected, count)
self.assertEqual(count, expected)
@@ -80,5 +84,34 @@ class test_nsnap04(wttest.WiredTigerTestCase, suite_subprocess):
self.session.snapshot("name=0")
self.check_named_snapshot(0, 2 * self.nrows_per_itr)
+ def test_include_updates(self):
+ # Populate a table
+ end = start = 0
+ SimpleDataSet(self, self.uri, 0, key_format='i').populate()
+
+ snapshots = []
+ c = self.session.open_cursor(self.uri)
+ for i in xrange(self.nrows_per_itr):
+ c[i] = "some value"
+
+ self.session.begin_transaction("isolation=snapshot")
+ count = 0
+ for row in c:
+ count += 1
+ self.session.snapshot("name=0,include_updates=true")
+
+ self.check_named_snapshot(0, self.nrows_per_itr)
+
+ # Insert some more content using the active session.
+ for i in xrange(self.nrows_per_itr):
+ c[self.nrows_per_itr + i] = "some value"
+
+ self.check_named_snapshot(0, 2 * self.nrows_per_itr)
+ # Ensure transactions not tracking the snapshot don't see the updates
+ self.check_named_snapshot(0, self.nrows_per_itr, skip_snapshot=True)
+ self.session.commit_transaction()
+ # Ensure content is visible to non-snapshot transactions after commit
+ self.check_named_snapshot(0, 2 * self.nrows_per_itr, skip_snapshot=True)
+
if __name__ == '__main__':
wttest.run()
diff --git a/test/suite/wtdataset.py b/test/suite/wtdataset.py
index cb77735510c..74e07e24e93 100644
--- a/test/suite/wtdataset.py
+++ b/test/suite/wtdataset.py
@@ -49,7 +49,7 @@ class BaseDataSet(object):
def fill(self):
c = self.testcase.session.open_cursor(self.uri, None)
- for i in range(1, self.rows + 1):
+ for i in xrange(1, self.rows + 1):
c[self.key(i)] = self.value(i)
c.close()
@@ -166,7 +166,7 @@ class SimpleIndexDataSet(SimpleDataSet):
# Check values in the index.
idxcursor = self.testcase.session.open_cursor(self.indexname)
- for i in range(1, self.rows + 1):
+ for i in xrange(1, self.rows + 1):
k = self.key(i)
v = self.value(i)
ik = (v, k) # The index key is columns=(v,k).