1#!/usr/bin/env python 2# 3# Public Domain 2014-2018 MongoDB, Inc. 4# Public Domain 2008-2014 WiredTiger, Inc. 5# 6# This is free and unencumbered software released into the public domain. 7# 8# Anyone is free to copy, modify, publish, use, compile, sell, or 9# distribute this software, either in source code form or as a compiled 10# binary, for any purpose, commercial or non-commercial, and by any 11# means. 12# 13# In jurisdictions that recognize copyright laws, the author or authors 14# of this software dedicate any and all copyright interest in the 15# software to the public domain. We make this dedication for the benefit 16# of the public at large and to the detriment of our heirs and 17# successors. We intend this dedication to be an overt act of 18# relinquishment in perpetuity of all present and future rights to this 19# software under copyright law. 20# 21# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27# OTHER DEALINGS IN THE SOFTWARE. 28# 29# test_readonly02.py 30# Readonly: Test readonly mode with illegal config combinations 31# and error checking during updates. 32# 33 34from helper import copy_wiredtiger_home 35from suite_subprocess import suite_subprocess 36import os, wiredtiger, wttest 37 38class test_readonly02(wttest.WiredTigerTestCase, suite_subprocess): 39 tablename = 'table:test_readonly02' 40 create = True 41 create_params = 'key_format=i,value_format=i' 42 entries = 10 43 44 conn_params = \ 45 'create,statistics=(fast),' + \ 46 'log=(enabled,file_max=100K,zero_fill=true),' + \ 47 'operation_tracking=(enabled=false),' 48 conn_params_rd = \ 49 'create,readonly=true,statistics=(fast),' + \ 50 'log=(enabled,zero_fill=false),' + \ 51 'operation_tracking=(enabled=false),' 52 conn_params_rdcfg = \ 53 'create,readonly=true,statistics=(fast),log=(enabled),' + \ 54 'operation_tracking=(enabled=false),' 55 56 # 57 # Run to make sure incompatible configuration options return an error. 58 # The situations that cause failures (instead of silent overrides) are: 59 # 1. setting readonly on a new database directory 60 # 2. an unclean shutdown and reopening readonly 61 # 3. logging with zero-fill enabled and readonly 62 # 63 badcfg1 = 'log=(enabled,zero_fill=true)' 64 65 def setUpConnectionOpen(self, dir): 66 self.home = dir 67 rdonlydir = dir + '.rdonly' 68 # 69 # First time through check readonly on a non-existent database. 70 # 71 if self.create: 72 # 1. setting readonly on a new database directory 73 # Setting readonly prevents creation so we should see an 74 # error because the lock file does not exist. 75 msg = '/No such file/' 76 if os.name != 'posix': 77 msg = '/cannot find the file/' 78 os.mkdir(rdonlydir) 79 self.assertRaisesWithMessage(wiredtiger.WiredTigerError, 80 lambda: self.wiredtiger_open( 81 rdonlydir, self.conn_params_rd), msg) 82 83 self.create = False 84 conn = self.wiredtiger_open(dir, self.conn_params) 85 return conn 86 87 def check_unclean(self): 88 backup = "WT_COPYDIR" 89 copy_wiredtiger_home(self.home, backup, True) 90 msg = '/needs recovery/' 91 # 2. an unclean shutdown and reopening readonly 92 self.assertRaisesWithMessage(wiredtiger.WiredTigerError, 93 lambda: self.wiredtiger_open(backup, self.conn_params_rd), msg) 94 95 def close_checkerror(self, cfg): 96 ''' Close the connection and reopen readonly''' 97 # 98 # Close the original connection. Reopen readonly and also with 99 # the given configuration string. 100 # 101 self.close_conn() 102 conn_params = self.conn_params_rd + cfg 103 msg = '/Invalid argument/' 104 self.assertRaisesWithMessage(wiredtiger.WiredTigerError, 105 lambda: self.wiredtiger_open(self.home, conn_params), msg) 106 107 def test_readonly(self): 108 tablearg = self.tablename 109 self.session.create(tablearg, self.create_params) 110 c = self.session.open_cursor(tablearg, None, None) 111 for i in range(self.entries): 112 c[i+1] = i % 255 113 # Check for an error on an unclean recovery/restart. 114 self.check_unclean() 115 116 # Close the connection. Reopen readonly with other bad settings. 117 # 3. logging with zero-fill enabled and readonly 118 self.close_checkerror(self.badcfg1) 119 120if __name__ == '__main__': 121 wttest.run() 122