1 # Tests of Python-specific parts of the xapian bindings.
3 # Copyright (C) 2007,2008 Lemur Consulting Ltd
4 # Copyright (C) 2008,2009 Olly Betts
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License as
8 # published by the Free Software Foundation; either version 2 of the
9 # License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
28 from testsuite
import *
30 def set_master(masterpath
, srcpath
):
31 # Take a copy of the source, to make modifications to.
32 if os
.path
.exists(masterpath
+ "_"):
33 shutil
.rmtree(masterpath
+ "_")
34 shutil
.copytree(srcpath
, masterpath
+ "_")
36 # Set a new uuid on the copy. FIXME: Needs updating for glass where you
37 # can't just update the uuid like this.
39 xapian
.WritableDatabase(masterpath
+ "__", xapian
.DB_CREATE_OR_OVERWRITE
)
40 os
.unlink(os
.path
.join(masterpath
+ "_", "iamchert"))
41 os
.rename(os
.path
.join(masterpath
+ "__", "iamchert"),
42 os
.path
.join(masterpath
+ "_", "iamchert"))
43 shutil
.rmtree(masterpath
+ "__")
45 # Replace the current master with the copy of the source.
46 # Note that this isn't an atomic replace, so we'll sometimes get errors
47 # such as "NetworkError: Unable to fully synchronise: Can't open database:
48 # Cannot open tables at consistent revisions" - the replication protocol
49 # should recover happily from this, though.
50 if os
.path
.exists(masterpath
):
51 os
.rename(masterpath
, masterpath
+ "__")
52 os
.rename(masterpath
+ '_', masterpath
)
53 if os
.path
.exists(masterpath
+ "__"):
54 shutil
.rmtree(masterpath
+ "__")
56 def test_replication_concurrency():
57 """Test concurrent replication and modification
61 builddir
= os
.environ
['abs_builddir']
62 dbsdir
= os
.path
.join(builddir
, 'dbs_replication')
63 if not os
.path
.isdir(dbsdir
):
66 masterpath
= os
.path
.join(dbsdir
, 'master')
67 firstpath
= os
.path
.join(dbsdir
, 'first')
68 secondpath
= os
.path
.join(dbsdir
, 'second')
69 slavepath
= os
.path
.join(dbsdir
, 'slave')
70 if os
.path
.isdir(masterpath
):
71 shutil
.rmtree(masterpath
)
72 if os
.path
.isdir(slavepath
):
73 shutil
.rmtree(slavepath
)
76 expect_exception(xapian
.DatabaseOpeningError
,
77 "Couldn't stat '" + dbsdir
+ "/slave' (No such file or directory)",
78 xapian
.Database
, slavepath
)
81 serverp
= subprocess
.Popen(('../../xapian-core/bin/xapian-replicate-server',
90 starttime
= time
.time()
91 if not os
.path
.isdir(firstpath
):
92 firstdb
= xapian
.WritableDatabase(firstpath
, xapian
.DB_CREATE_OR_OVERWRITE
)
93 # Make an initial, large database
95 print "Building initial database ..."
96 for num
in xrange(1, doccount1
):
100 firstdb
.add_document(doc
)
101 if num
% 100000 == 0:
102 print "%d documents..." % num
103 firstdb
.set_metadata('dbname', '1')
107 # The secondary database gets modified during the test, so needs to be
109 shutil
.rmtree(secondpath
)
110 if not os
.path
.isdir(secondpath
):
111 seconddb
= xapian
.WritableDatabase(secondpath
, xapian
.DB_CREATE_OR_OVERWRITE
)
112 # Make second, small database
114 print "Building secondary database ..."
115 for num
in xrange(1, doccount2
):
116 doc
=xapian
.Document()
118 doc
.add_value(1, val
)
119 seconddb
.add_document(doc
)
120 if num
% 100000 == 0:
121 print "%d documents..." % num
122 seconddb
.set_metadata('dbname', '2')
126 if time
.time() - starttime
< 1:
127 time
.sleep(1) # Give server time to start
130 set_master(masterpath
, firstpath
)
131 clientp
= subprocess
.Popen(('../../xapian-core/bin/xapian-replicate',
134 os
.path
.join(dbsdir
, 'slave'),
140 time
.sleep(1) # Give client time to start
141 expect(xapian
.Database(slavepath
).get_metadata('dbname'), '1')
143 for count
in xrange(10):
144 # Test that swapping between databases doesn't confuse replication.
145 for count2
in xrange(2):
146 set_master(masterpath
, secondpath
)
148 set_master(masterpath
, firstpath
)
151 # Test making changes to the database.
152 set_master(masterpath
, secondpath
)
153 masterdb
= xapian
.WritableDatabase(masterpath
, xapian
.DB_OPEN
)
154 print "making 100 changes"
155 for num
in xrange(100):
156 masterdb
.set_metadata('num%d' % num
, str(num
+ count
))
161 # Allow time for the replication client to catch up with the
164 expect(xapian
.Database(slavepath
).get_metadata('dbname'), '2')
165 expect(xapian
.Database(slavepath
).get_metadata('num99'), str(99 + count
))
168 if clientp
is not None:
169 os
.kill(clientp
.pid
, 9)
171 os
.kill(serverp
.pid
, 9)
173 #shutil.rmtree(dbsdir)
175 # Run all tests (ie, callables with names starting "test_").
176 if not runtests(globals(), sys
.argv
[1:]):
179 # vim:syntax=python:set expandtab: