# 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)