
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)
