trove,测试,db小解析
# Copyright 2014 Tesora Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License. """
Tests database migration scripts for mysql. To run the tests, you'll need to set up db user named 'openstack_citest'
with password 'openstack_citest' on localhost. This user needs db
admin rights (i.e. create/drop database) """
import glob
import os import migrate.versioning.api as migration_api
from migrate.versioning import repository
from oslo_concurrency import processutils
from oslo_log import log as logging
from proboscis import after_class
from proboscis.asserts import assert_equal
from proboscis.asserts import assert_true
from proboscis import before_class
from proboscis import SkipTest
from proboscis import test
import sqlalchemy
import sqlalchemy.exc from trove.common.i18n import _
import trove.db.sqlalchemy.migrate_repo
from trove.tests.util import event_simulator GROUP = "dbaas.db.migrations"
LOG = logging.getLogger(__name__) @test(groups=[GROUP])
class ProjectTestCase(object):
"""Test migration scripts integrity.""" @test
def test_all_migrations_have_downgrade(self):
topdir = os.path.normpath(os.path.join(os.path.dirname(__file__),
os.pardir, os.pardir, os.pardir))
py_glob = os.path.join(topdir, "trove", "db", "sqlalchemy",
"migrate_repo", "versions", "*.py") missing_downgrade = []
for path in glob.iglob(py_glob):
has_upgrade = False
has_downgrade = False
with open(path, "r") as f:
for line in f:
if 'def upgrade(' in line:
has_upgrade = True
if 'def downgrade(' in line:
has_downgrade = True if has_upgrade and not has_downgrade:
fname = os.path.basename(path)
missing_downgrade.append(fname) helpful_msg = (_("The following migration scripts are missing a "
"downgrade implementation:\n\t%s") %
'\n\t'.join(sorted(missing_downgrade)))
assert_true(not missing_downgrade, helpful_msg) @test(depends_on_classes=[ProjectTestCase],
groups=[GROUP])
class TestTroveMigrations(object):
"""Test sqlalchemy-migrate migrations."""
USER = "openstack_citest"
PASSWD = "openstack_citest"
DATABASE = "openstack_citest" @before_class
def setUp(self):
event_simulator.allowable_empty_sleeps = 1 @after_class
def tearDown(self):
event_simulator.allowable_empty_sleeps = 0 def __init__(self):
self.MIGRATE_FILE = trove.db.sqlalchemy.migrate_repo.__file__
self.REPOSITORY = repository.Repository(
os.path.abspath(os.path.dirname(self.MIGRATE_FILE)))
self.INIT_VERSION = 0 def _get_connect_string(self, backend, database=None):
"""Get database connection string."""
args = {'backend': backend,
'user': self.USER,
'passwd': self.PASSWD}
template = "%(backend)s://%(user)s:%(passwd)s@localhost"
if database is not None:
args['database'] = database
template += "/%(database)s"
return template % args def _is_backend_avail(self, backend):
"""Check database backend availability."""
connect_uri = self._get_connect_string(backend)
engine = sqlalchemy.create_engine(connect_uri)
try:
connection = engine.connect()
except Exception:
# any error here means the database backend is not available
return False
else:
connection.close()
return True
finally:
if engine is not None:
engine.dispose() def _execute_cmd(self, cmd=None):
"""Shell out and run the given command."""
out, err = processutils.trycmd(cmd, shell=True)
# Until someone wants to rewrite this to avoid the warning
# we need to handle it for newer versions of mysql
valid_err = err == '' or \
err == 'mysql: [Warning] Using a password on the ' \
'command line interface can be insecure.\n'
assert_true(valid_err,
"Failed to run: '%(cmd)s' "
"Output: '%(stdout)s' "
"Error: '%(stderr)s'" %
{'cmd': cmd, 'stdout': out, 'stderr': err}) def _reset_mysql(self):
"""Reset the MySQL test database Drop the MySQL test database if it already exists and create
a new one.
"""
sql = ("drop database if exists %(database)s; "
"create database %(database)s;" % {'database': self.DATABASE})
cmd = ("mysql -u \"%(user)s\" -p%(password)s -h %(host)s "
"-e \"%(sql)s\"" % {'user': self.USER, 'password': self.PASSWD,
'host': 'localhost', 'sql': sql})
self._execute_cmd(cmd) @test
def test_mysql_migration(self):
db_backend = "mysql+pymysql"
# Gracefully skip this test if the developer do not have
# MySQL running. MySQL should always be available on
# the infrastructure
if not self._is_backend_avail(db_backend):
raise SkipTest("MySQL is not available.")
self._reset_mysql()
connect_string = self._get_connect_string(db_backend, self.DATABASE)
engine = sqlalchemy.create_engine(connect_string)
self._walk_versions(engine)
engine.dispose() def _walk_versions(self, engine=None): //跑版本
"""Walk through and test the migration scripts Determine latest version script from the repo, then
upgrade from 1 through to the latest, then downgrade from
the latest back to 1, with no data in the databases. This
just checks that the schema itself upgrades and downgrades
successfully.
"""
# Place the database under version control
migration_api.version_control(engine, self.REPOSITORY,
self.INIT_VERSION)
assert_equal(self.INIT_VERSION,
migration_api.db_version(engine, self.REPOSITORY)) LOG.debug('Latest version is %s' % self.REPOSITORY.latest)
versions = range(self.INIT_VERSION + 1, self.REPOSITORY.latest + 1) //从最开始的那版跑到最新那版+1终止,INIT_VERSION初始值是0,所以要+ 1,range函数的终止是后面那个参数,但不会到那个参数,相当于++i # Snake walk from version 1 to the latest, testing the upgrade paths.
# upgrade -> downgrade -> upgrade
for version in versions:
self._migrate_up(engine, version)
self._migrate_down(engine, version - 1)
self._migrate_up(engine, version) # Now snake walk back down to version 1 from the latest, testing the
# downgrade paths.
# downgrade -> upgrade -> downgrade
for version in reversed(versions):
self._migrate_down(engine, version - 1)
self._migrate_up(engine, version)
self._migrate_down(engine, version - 1) def _migrate_down(self, engine, version): //版本往上跑
"""Migrate down to an old version of database."""
migration_api.downgrade(engine, self.REPOSITORY, version)
assert_equal(version,
migration_api.db_version(engine, self.REPOSITORY)) def _migrate_up(self, engine, version): //版本往下跑
"""Migrate up to a new version of database."""
migration_api.upgrade(engine, self.REPOSITORY, version)
assert_equal(version,
migration_api.db_version(engine, self.REPOSITORY)) 这个文件感觉大部分就是在做版本的问题,看看升级版本或者降级版本的时候,数据是不是会被破坏,我是这么理解的。。。
trove,测试,db小解析的更多相关文章
- 屠龙之路_击败DB小boss_FifthDay
摘要:服务器大魔王被击败的消息传到了恶龙boss那里,恶龙大怒派出了自己的首级大将DB人称小boss,但小boss的名号并没有吓到七位屠龙勇士,经过他们齐心协力的进攻,最终击败了DB,小boss临死前 ...
- 使用Appium 测试微信小程序和微信公众号方法
由于腾讯系QQ.微信等都是基于腾讯自研X5内核,不是google原生webview,需要打开TBS内核Inspector调试功能才能用Chrome浏览器查看页面元素,并实现Appium自动化测试微信小 ...
- Appium之测试微信小程序
坚持原创输出,点击蓝字关注我吧 作者:清菡 博客:Oschina.云+社区.知乎等各大平台都有. 目录 一.往期回顾 二.测试微信小程序 1.准备工作 2.操作步骤 3.注意 4.强制设置安卓的进程 ...
- ESA2GJK1DH1K微信小程序篇: 测试微信小程序APUConfig给WI-Fi模块配网并绑定设备,并通过MQTT控制设备
前言(源码使用介绍在最后) 一,微信小程序篇小程序下载(该源码为这节测试源代码) 二.有多少人一直在期盼着小程序可以实现SmartConfig或者Airkiss的功能? 来吧!我的这种方式包您满意. ...
- Miller-Rabin素数测试学习小计
1.Miller-Rabin是干啥的?它是用来检测一个数字(一般是很大的数字)是不是素数: 2.Miller-Rabin算法基于的两个定理: (1)费尔马小定理:如果p是一个素数,且0<a< ...
- fastJson解析复杂的json字符串,经测试已经成功解析
要解析的json数据格式为: HTTP/1.1 200 OK Content-Type: text/jsv Content-Length: length { ResponseStatus: { }, ...
- 自己动手编写IPv4地址包含关系测试的小脚本
工作中需要对地址包含关系进行测试,现有ipaddress标准库和IPy无法满足,于是自己动手编写小脚本,主要实现== , in, <等专用功能,其他功能可以后续用到再补充,例如迭代打印网段内所有 ...
- java对象传递小解析
先上代码: import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder ...
- Web进行压力测试的小工具
在Linux下对Web进行压力测试的小工具有很多,比较出名的有AB.虽然AB可以运行在windows下,但对于想简单界面操作的朋友有点不太习惯.其实vs.net也提供压力测试功能但显然显得太重了,在测 ...
随机推荐
- 用Python实现gmail邮箱服务,实现两个邮箱之间的绑定(上)
一.本程序的起源 当我决定去中科院实习的时候,我给刘奎恩老师发了封邮件.我对此事是非常看重的,因此经常使用浏览器,打开gmail去查看刘老师有没有给我回复.因为gmail的新邮件推送的功能仅限于打开浏 ...
- Xcode5和ObjC新特性
Welcome to Xcode 5 这是我的WWDC2013系列笔记中的一篇,完整的笔记列表请参看这篇总览.本文仅作为个人记录使用,也欢迎在许可协议范围内转载或使用,但是还烦请保留原文链接,谢谢您的 ...
- cubie两种固定MAC地址的方法
1.修改 /etc/init.d/networking 配置文件 在(a)代码的后面添加上(b)这段代码 (a)case "$1" in start) :5e #MAC地址可改 2 ...
- make deb for debian/ubuntu, package software for debian/ubuntu
here you may find useful information: =====================X8---------------------------------8X==== ...
- Linux下逻辑卷创建与管理
用虚拟机加一块硬盘后,查看硬盘状况,使用fdisk-l命令: [root@jerrybj ~]# fdisk -l Disk /dev/sda: 21.4 GB, 21474836480 bytes ...
- android:minSdkVersion 之我见
在 新建一个 android project 时,要求输入 minSdkVersion 这一项,一般我们是指定和我们使用的 SDK 版本相一致的 API Level. 然后,在androidManif ...
- mysql处理存在则更新,不存在则插入(多列唯一索引)
mysql处理某个唯一索引时存在则更新,不存在则插入的情况应该是很常见的,网上也有很多类似的文章,我今天就讲讲当这个唯一的索引是多列唯一索引时可能会遇到的问题和方法. 方法一: 使用 INSERT I ...
- Android Device Chooser中显示Target unknown解决方法
手机插在电脑上准备调试程序来着,通过eclipse运行时,弹出的Android Device Chooser中显示设备名是?????,Target未知,无法继续运行. 可以通过以下步骤解决(Ubunt ...
- (转)Tomcat 配置成https协议
Tomcat 配置成https协议 TomcatXMLServlet 在命令提示符窗口,进入Tomcat目录,执行以下命令: keytool -genkey -alias tomcat -keyal ...
- Java代码到字节码——第一部分
Java代码到字节码——第一部分 原文地址 作者:James Bloom 译者:张坤 理解在Java虚拟机中Java代码如何别被编译成字节码并执行是非常重要的,因为这可以帮助你理解你的程序在运行时发生 ...