myserver control

>>> from lovely.testlayers import mysql
>>> import tempfile, os
>>> tmp = tempfile.mkdtemp()
>>> dbDir = os.path.join(tmp, 'db')
>>> dbDirFake = os.path.join(tmp, 'dbfake')
>>> dbName = 'testing'

Let us create a mysql server.

>>> srv = mysql.Server(dbDir, port=17777)

And init the db.

>>> srv.initDB()
>>> srv.start()
>>> import time
>>> time.sleep(3)
>>> srv.createDB(dbName)

Now we can get a list of databases.

>>> sorted(srv.listDatabases())
['mysql', 'test', 'testing']

If no mysql server is installed on the system we will get an exception:

>>> srv.orig_method = srv.mysqld_path
>>> srv.mysqld_path = lambda: None

>>> srv.start()
Traceback (most recent call last):
IOError: mysqld was not found. Is a MySQL server installed?

>>> srv.mysqld_path = srv.orig_method

Run SQL scripts

We can run scripts from the filesystem.

>>> script = os.path.join(tmp, 'ascript.sql')
>>> f = file(script, 'w')
>>> f.write("""drop table if exists a; create table a (title varchar(64));""")
>>> f.close()
>>> srv.runScripts(dbName, [script])

Dump and Restore

Let us make a dump of our database

>>> dumpA = os.path.join(tmp, 'a.sql')
>>> srv.dump(dbName, dumpA)

And now some changes

>>> import _mysql
>>> conn = _mysql.connect(host='127.0.0.1', port=17777, user='root', db=dbName)
>>> for i in range(5):
...     conn.query('insert into a values(%i)' % i)
>>> conn.commit()
>>> conn.close()

Another dump.

>>> dumpB = os.path.join(tmp, 'b.sql')
>>> srv.dump(dbName, dumpB)

We restore dumpA and the table is emtpy.

>>> srv.restore(dbName, dumpA)
>>> conn = _mysql.connect(host='127.0.0.1', port=17777, user='root', db=dbName)
>>> conn.query('select count(*) from a')
>>> conn.store_result().fetch_row()
(('0',),)
>>> conn.close()

Now restore dumpB and we have our 5 rows back.

>>> srv.restore(dbName, dumpB)
>>> conn = _mysql.connect(host='127.0.0.1', port=17777, user='root', db=dbName)
>>> conn.query('select count(*) from a')
>>> conn.store_result().fetch_row()
(('5',),)
>>> conn.close()

If we try to restore a none existing file we gat a ValueError.

>>> srv.restore(dbName, 'asdf')
Traceback (most recent call last):
...
ValueError: No such file '.../asdf'
>>> srv.stop()

MySQLDB Scripts

We can generate a control script for use as commandline script.

The simplest script is just to define a server.

>>> dbDir2 = os.path.join(tmp, 'db2')
>>> main = mysql.MySQLDBScript(dbDir2, port=17777)
>>> main.start()
>>> sorted(main.srv.listDatabases())
['mysql', 'test']
>>> main.stop()

We can also define a database to be created upon startup.

>>> main = mysql.MySQLDBScript(dbDir2, dbName='hoschi', port=17777)
>>> main.start()
>>> sorted(main.srv.listDatabases())
['hoschi', 'mysql', 'test']
>>> main.stop()

The database is created only one time.

>>> main.start()
>>> main.stop()

And also scripts to be executed.

>>> main = mysql.MySQLDBScript(dbDir2, dbName='hoschi2',
...                          scripts=[script], port=17777)
>>> main.start()

Note that we used the same directory here so the other db is still there.

>>> sorted(main.srv.listDatabases())
['hoschi', 'hoschi2', 'mysql', 'test']

We can run the scripts again. Note that scripts should always be none-destructive. So if a schema update is due one just needs to run all scripts again.

>>> main.runscripts()
>>> main.stop()

MySQLDatabaseLayer

Let’s create a layer:

>>> layer = mysql.MySQLDatabaseLayer('testing')

We can get the store uri.

>>> layer.storeURI()
'mysql://localhost:16543/testing'
>>> layer.setUp()
>>> layer.tearDown()

The second time the server ist started it takes the snapshot.

>>> layer.setUp()
>>> layer.tearDown()

If we try to run setup twice or the port is occupied, we get an error.

>>> layer.setUp()
>>> layer.setUp()
Traceback (most recent call last):
RuntimeError: Port already listening: 16543
>>> layer.tearDown()

We can have appsetup definitions and sql scripts. There is also a convinience class that let’s us execute sql statements as setup.

>>> setup = mysql.ExecuteSQL('create table testing (title varchar(32))')
>>> layer = mysql.MySQLDatabaseLayer('testing', setup=setup)
>>> layer.setUp()
>>> layer.tearDown()
>>> layer = mysql.MySQLDatabaseLayer('testing', setup=setup)
>>> layer.setUp()
>>> layer.tearDown()

Also if the database name is different, the same snapshots can be used.

>>> layer2 = mysql.MySQLDatabaseLayer('testing2', setup=setup)
>>> layer2.setUp()
>>> layer2.tearDown()

If we do not provide the snapsotIdent the ident is built by using the dotted name of the setup callable and the hash of the arguments.

>>> layer.snapshotIdent
u'lovely.testlayers.mysql.ExecuteSQLe449d7734c67c100e0662d3319fe3f410e78ebcf'

Let us provide an ident and scripts.

>>> layer = mysql.MySQLDatabaseLayer('testing3', setup=setup,
...                                  snapshotIdent='blah',
...                                  scripts=[script])
>>> layer.snapshotIdent
'blah'
>>> layer.scripts
['/.../ascript.sql']

On setup the snapshot with the setup is created, therefore setup is called with the server as argument.

>>> layer.setUp()

Upon testSetUp this snapshot is now restored.

>>> layer.testSetUp()

So now we should have the table there.

>>> conn = _mysql.connect(host='127.0.0.1', port=16543, user='root', db=dbName)
>>> conn.query('select * from testing')
>>> conn.store_result().fetch_row()
()
>>> conn.close()

Let us add some data (we are now in a test):

>>> conn = _mysql.connect(host='127.0.0.1', port=16543, user='root', db=dbName)
>>> conn.query("insert into testing values('hoschi')")
>>> conn.commit()
>>> conn.query('select * from testing')
>>> conn.store_result().fetch_row()
(('hoschi',),)
>>> conn.close()
>>> layer.testTearDown()
>>> layer.tearDown()

Finally do some cleanup:

>>> import shutil
>>> shutil.rmtree(tmp)